home *** CD-ROM | disk | FTP | other *** search
- Date: Fri, 05 Jun 87 00:18:28 EDT
- From: Peter DiCamillo <CMSMAINT%BROWNVM.BITNET@forsythe.stanford.edu>
- Subject: BINHEX Command for CMS
-
- BINHEX is a command I've written for IBM VM/CMS systems to process
- BinHex (HQX) and MacBinary format files stored on CMS disks. BINHEX
- will check for CRC and other errors in the files, display the header
- information (Mac filename, creator, type, flags etc.), and convert
- files between the two formats. User documentation is contained in
- BINHEX HELPCMS; directions for creating BINHEX MODULE are in the
- main source file, BINHEX ASSEMBLE.
-
- Peter DiCamillo, Brown University Computer Center
- BITNET: CMSMAINT@BROWNVM
- Internet: CMSMAINT%BROWNVM@WISCVM.WISC.EDU
-
- ---------------------------------------------------------------------
- Contents:
- BINHEX ASSEMBLE 2453 lines Main program
- BINHEX HELPCMS 224 lines User documentation
- XMDMGEN C 62 lines Waterloo C pgm. to generate XMDMTAB
- XMDMTAB ASSEMBLE 46 lines Table for XMODEM CRC calculation
-
- Note: After uploading the ASSEMBLE files, they must be converted to
- fixed-length 80-byte records in order to be assembled. For
- example: COPYFILE BINHEX ASSEMBLE A = = = (LRECL 80 RECFM F
-
- ---------- start of BINHEX ASSEMBLE: 2453 lines follow --------------
- BINHEX TITLE 'Program to Process BinHex and MacBinary Format Files'
- BINHEX CSECT
- SPACE
- ***********************************************************************
- * *
- * Name: *
- * BINHEX *
- * *
- * Author: *
- * Peter DiCamillo *
- * Brown University Computer Center *
- * Box 1885 *
- * Providence, RI 02912 *
- * (401) 863-2221 *
- * BITNET: CMSMAINT@BROWNVM *
- * ARPANET: CMSMAINT%BROWNVM@WISCVM.WISC.EDU *
- * *
- * Function: *
- * BINHEX checks, describes, and converts Macintosh files *
- * stored in CMS. It is able to work with both MacBinary for- *
- * mat (Macterminal, BinHex 5.0) and BinHex format (BinHex 4.0) *
- * files. *
- * *
- * Command format: *
- * BINHEX ?|Check|Describe|COnvert fn <ft <fm>> <( options <)>> *
- * See the HELP file for detailed information. *
- * *
- * Normal Exits: *
- * Returns to CMS with R15 = 0. For the ?, Check, and Describe *
- * operands, repsonses are generated before returning. *
- * *
- * Error Conditions: *
- * Returns to CMS with a non-zero return code after typing an *
- * error message. Errors messgae and return codes are listed in *
- * the HELP file. *
- * *
- * CMS System Calls: *
- * CMS nucleus routines called via BALR: *
- * ESTATE, ESTATEW, ADTLKP, RDBUF, WRBUF, FINIS *
- * CMS routines called via SVC 202 or 203: *
- * IDENTIFY, CONWAIT, TYPLIN, ATTN, EXECCOMM, DMSERR, LINEDIT *
- * *
- * External References: *
- * For CRC calculation, BINHEX uses a table defined in XMDMTAB *
- * ASSEMBLE. *
- * *
- * Attributes: *
- * BINHEX loads in the user program area. In order to call *
- * nucleus routines via BALR (for speed), it disables *
- * interrupts and runs with the system storage key. *
- * *
- ***********************************************************************
- EJECT
- ***********************************************************************
- * *
- * Module Generation: *
- * To create a new BINHEX MODULE, use the commands: *
- * GLOBAL TXTLIB DMSSP CMSLIB *
- * ASSEMBLE BINHEX *
- * ASSEMBLE XMDMTAB *
- * LOAD BINHEX *
- * GENMOD BINHEX *
- * *
- * Update History: *
- * June 1, 1987: Initial implementation, Peter DiCamillo *
- * *
- ***********************************************************************
- EJECT
- PRINT NOGEN
- REGEQU
- USING *,R15
- STM R0,R15,REGSAVE Save all registers
- LR R11,R15 Use R11-R13 as base registers
- LA R12,2048(R11)
- LA R12,2048(R12)
- LA R13,2048(R12)
- LA R13,2048(R13)
- DROP R15
- USING BINHEX,R11,R12,R13
- USING NUCON,0 Address nucon
- L R10,AFVS R10 = FVSECT base register
- USING FVSECT,R10
- DMSKEY NUCLEUS We need system key and no
- SSM =X'00' interruptions
- SR R15,R15
- ST R15,RTNCODE Return code initialized to zero
- ST R15,CPS Initailize rate to zero
- MVI FLAGS,0 All flags = 0
- MVI FLAGS2,0
- MVI OPRCODE,C' ' First operand unknown
- MVC IFM(2),=CL2'*' Default input mode is "*"
- MVC OFM(2),=CL2'*' Default output mode is "*"
- L R2,=A(TOASCSTD) Set default EBCDIC to ASCII table
- ST R2,TOASCADR
- L R2,=A(FRASCSTD) Set default ASCII to EBCDIC table
- ST R2,FRASCADR
- BAL R14,GETID Get local node id
- CLC NODEID(8),BROWNID If Brown, use local tables
- BNE XTABOK
- L R2,=A(TOASCBRN)
- ST R2,TOASCADR
- L R2,=A(FRASCBRN)
- ST R2,FRASCADR
- XTABOK EQU *
- L R2,=A(WRITBUFF) R2 -> buffer
- L R3,=A(VALIDTAB) R3 -> TRT table
- MVI 0(R3),X'FF' Initialize VALIDTAB for TRTs
- MVC 1(255,R3),0(R3)
- L R4,=A(BINTOASC) R4 -> ASCII character list
- MVC 0(64,R2),0(R4) Copy valid ASCII characters
- L R4,FRASCADR R2 -> ASCII-to-EBCDIC table
- TR 0(64,R2),0(R4) Convert to valid EBCDIC characters
- LA R4,64 R4 = count for BCT
- SR R5,R5 R5 = 0 for IC
- VINITLP EQU * Loop to fill-in VALIDTAB
- IC R5,0(R2) Get new character in R5
- LA R6,0(R3,R5) R6 -> position in table
- MVI 0(R6),0 Store zero there
- LA R2,1(R2) R2 -> next character
- BCT R4,VINITLP Repeat for all 64 character
- B OPERCHK Skip over save area
- SPACE
- REGSAVE DS 8D Register save area
- RTNCODE EQU REGSAVE+60 Return code at location for R15
- EJECT
- * Check for valid first operand (function)
- OPERCHK LA R1,8(R1) R1 -> operand
- CLI 0(R1),X'FF' Operand there at all?
- BE BADFMT No, give error message
- LA R3,8 Get operand length in R3
- LA R2,7(R1) R2 -> last byte
- OPRLENLP EQU * Loop to get length
- CLI 0(R2),C' ' At non-blank?
- BNE HAVEOPRL Yes, length in R3
- BCTR R2,0 R2 -> previous byte
- BCT R3,OPRLENLP Decrement and repeat
- B BADFMT All blank is error
- SPACE
- HAVEOPRL BCTR R3,0 Decrement length for EX
- LA R2,OPRTAB R2 -> operand table
- OPRTBCHK EQU * Look for match in table
- CLI 0(R2),X'FF' At table end?
- BE BADFMT Yes, format error
- EX R3,OPRCLC Found a match?
- BE USEOPR Yes, handle operand
- LA R2,12(R2) R2 -> next operand
- B OPRTBCHK Try again
- SPACE
- OPRCLC CLC 0(*-*,R2),0(R1) Compare table entry to operand
- SPACE
- USEOPR L R2,8(R2) R2 -> operand code
- BR R2 Execute code for operand
- SPACE
- CHKOPR MVI OPRCODE,C'C' Set code C for CHECK
- B READID
- SPACE
- CVTOPR MVI OPRCODE,C'V' Set code V for CONVERT
- B READID
- SPACE
- DESCOPR MVI OPRCODE,C'D' Set code D for DESCRIBE
- B READID
- SPACE
- QUESOPR EQU * For ?, type command format
- WRTERM 'Format is: BINHEX ?|Check|Describe|COnvert fn ft <fm> X
- <( options <)>>'
- WRTERM ' Options: <To fm> <Rate cps> <Stack> <Lifo> <Fifo> <SX
- TEm stemname>'
- B CMSRTN Return right away
- SPACE
- * After function operand, get file id
- READID LA R1,8(R1) R1 -> possible FN
- CLI 0(R1),X'FF' Error if missing or "*"
- BE BADFMT
- CLI 0(R1),C'*'
- BE BADFMT
- MVC IFN(8),0(R1) Copy FN
- MVC IFT(8),=CL8'*' Set default filetype
- LA R1,8(R1) R1 -> possible FT
- CLI 0(R1),X'FF' Done if no FT, FM or options
- BE OPTDONE
- CLI 0(R1),C'(' If '(', start options
- BE OPTSCAN
- MVC IFT(8),0(R1) Copy FT
- LA R1,8(R1) R1 -> past FT
- CLI 0(R1),X'FF' Done if no FM or options
- BE OPTDONE
- CLI 0(R1),C'(' If '(', start options
- BE OPTSCAN
- CLI 2(R1),C' ' 3rd character of FM must be blank
- BNE BADFMT
- CLC 0(2,R1),=CL2'*' Skip copy if default specified
- BE IFMDONE
- MVC IFM(2),0(R1) Copy filemode for input
- CLI IFM+1,C' ' If no mode number, use '1'
- BNE IFMDONE
- MVI IFM+1,C'1'
- IFMDONE LA R1,8(R1) R1 -> next argument
- CLI 0(R1),X'FF' Done if no options
- BE OPTDONE
- CLI 0(R1),C'(' If '(', start options
- BE OPTSCAN
- * Else command format error
- BADFMT LR R2,R1 R2 = scan pointer
- S R2,=F'8' Point to previous token
- DMSERR NUM=1,LET=E,SUB=(CHARA,(R2)), X
- TEXT='Error in command after ''........'''
- DMSERR NUM=2,LET=I, X
- TEXT='Issue BINHEX ? or HELP CMS BINHEX for more informaX
- tion'
- MVI RTNCODE+3,24 Set return code
- B CMSRTN Return to CMS
- SPACE
- * Process options
- OPTSCAN EQU * R1 -> '('
- NEWOPT LA R1,8(R1) R1 -> possible option
- CLI 0(R1),X'FF' Option there?
- BE OPTDONE No, done scanning
- CLI 0(R1),C')' Also done if ')'
- BE OPTDONE
- LA R3,8 Get option length in R3
- LA R2,7(R1) R2 -> last byte
- OPTLENLP EQU * Loop to get length
- CLI 0(R2),C' ' At non-blank?
- BNE HAVEOPTL Yes, length in R3
- BCTR R2,0 R2 -> previous byte
- BCT R3,OPTLENLP Decrement and repeat
- B BADOPT All blank is error
- SPACE
- HAVEOPTL BCTR R3,0 Decrement length for EX
- LA R2,OPTTAB R2 -> option table
- OPTTBCHK EQU * Look for match in table
- CLI 0(R2),X'FF' At table end?
- BE BADOPT Yes, format error
- EX R3,OPTCLC Found a match?
- BE USEOPT Yes, handle option
- LA R2,12(R2) R2 -> next option
- B OPTTBCHK Try again
- SPACE
- OPTCLC CLC 0(*-*,R2),0(R1) Compare table entry to option
- SPACE
- USEOPT L R2,8(R2) R2 -> option code
- BR R2 Execute code for option
- SPACE
- TOOPT EQU * TO option
- LA R1,8(R1) R1 -> filemode
- CLI 0(R1),X'FF' Error if mode missing
- BE BADMODE
- CLI 2(R1),C' ' Error if more than 2 characters
- BNE BADMODE
- MVC OFM(2),0(R1) Copy output filemode
- B NEWOPT
- SPACE
- STEMOPT EQU * STEM option
- LA R1,8(R1) R1 -> stem name
- CLI 0(R1),X'FF' Error if stem missing
- BE BADSTEM
- MVC STEMNAME(8),0(R1) Save stem name
- OI FLAGS2,EXECVAR Remember stem given
- LA R3,8 Get stem length in R3
- LA R2,7(R1) R2 -> last byte
- STMLENLP EQU * Loop to get length
- CLI 0(R2),C' ' At non-blank?
- BNE HAVESTML Yes, length in R3
- BCTR R2,0 R2 -> previous byte
- BCT R3,STMLENLP Decrement and repeat
- B BADSTEM Error if all blank
- SPACE
- HAVESTML ST R3,STEMSIZE Save length of stem name
- B NEWOPT
- SPACE
- BADMODE LR R2,R1 R2 -> bad filemode
- DMSERR NUM=48,LET=E,TEXT='Invalid mode ''........''', X
- SUB=(CHARA,(R2))
- MVI RTNCODE+3,24 Set return code
- B CMSRTN Return to CMS
- SPACE
- BADSTEM DMSERR NUM=637,LET=E,TEXT='Missing value for the ''STEM'' optiX
- on'
- MVI RTNCODE+3,24 Set return code
- B CMSRTN Return to CMS
- SPACE
- RATEOPT EQU * RATE option
- LA R1,8(R1) R1 -> rate
- CLI 0(R1),X'FF' Error if rate missing
- BE BADRATE
- BAL R14,DECCVT Convert to decimal in R2
- BNP BADRATE Error if result not positive
- ST R2,CPS Store rate
- B NEWOPT Ready for next option
- SPACE
- BADRATE LR R2,R1 R2 -> bad rate
- DMSERR NUM=10,LET=E,TEXT='Invalid rate ''........''', X
- SUB=(CHARA,(R2))
- MVI RTNCODE+3,24 Set return code
- B CMSRTN Return to CMS
- SPACE
- STKOPT EQU * STACK or FIFO option
- OI FLAGS,STKDESC Set flag to stack description
- B NEWOPT
- SPACE
- LIFOOPT EQU * LIFO option
- OI FLAGS,STKDESC+STKLIFO Set stack and FIFO flags
- B NEWOPT
- SPACE
- BADOPT LR R2,R1 R2 -> bad option
- DMSERR NUM=3,LET=E,TEXT='Invalid option ''........''', X
- SUB=(CHARA,(R2))
- MVI RTNCODE+3,24 Set return code
- B CMSRTN Return to CMS
- SPACE
- OPTDONE EQU * Done scanning plist
- * Check input file, get actual filemode, and check for BIN file
- LA R1,INPLIST Call STATE for input file
- L R15,AESTATE
- BALR R14,R15
- BNZ STATERR Check for any errors
- CLC IFT(8),=CL8'*' * or no filetype specified?
- BNE FTOK No, keep filetype
- MVC IFT(8),FVST Else copy from file we found
- FTOK CLC FVSIL(4),=F'256' Return error if lrecl too big
- BH LRECLERR
- L R2,FVSFSTAD R2 -> ADT for input file disk
- USING ADTSECT,R2
- IC R1,ADTM Fill-in actual disk letter and
- STC R1,IFM mode number for file which
- IC R1,FVSM+1 was found
- STC R1,IFM+1
- DROP R2
- CLI OFM,C'*' If OFM not filled-in, use input
- BNE MDNUMTST file disk letter
- IC R1,IFM
- STC R1,OFM
- MDNUMTST CLI OFM+1,C' ' If OFM not filled-in, use input
- BNE BINCHK file mode number
- IC R1,IFM+1
- STC R1,OFM+1
- BINCHK EQU * Check for MacBinary input file
- CLI FVSFV,C'F' Is recfm F?
- BNE NOTBIN No, not MacBinary
- CLC FVSIL(4),=F'128' Is lrecl 128?
- BNE NOTBIN No, not MacBinary
- OI FLAGS,MACBIN Else set flag for MacBinary
- NOTBIN EQU *
- * Define input file RDBUF plist
- LA R0,1 R0 = 1 for initializing
- SR R15,R15 R15 = 0 for initializing
- MVC INCMMD(8),=CL8'RDBUF' Command name
- STH R15,RDUN1 Unused halfword
- L R1,=A(READBUFF) Buffer address
- ST R1,RDADDR
- MVC RDBUFLTH(4),=F'256' Buffer size
- MVI RDFV,C'V' Record format (works for F too)
- MVI RDFLAG,X'20' Plist flag
- STH R15,RDUN2 Unused halfword
- ST R15,RDLGTH Bytes read
- ST R15,RDITEM Item number
- ST R0,RDITEC Item count
- ST R15,RDWP Write and read pointers
- ST R15,RDRP
- * If CONVERT specified, check output file status
- CLI OPRCODE,C'V' Convert specified?
- BNE INITDONE No, ready to start processing
- MVC OFN(8),IFN Output filename same as input
- MVC OFT(8),=CL8'BIN' Assume BIN for filetype
- TM FLAGS,MACBIN Is input MACBIN?
- BZ KEEPOFT No, BIN is correct
- MVC OFT(8),=CL8'HQX' Else use HQX
- KEEPOFT EQU * OFM already defined
- LA R1,OUTPLIST Call STATEW for output file
- L R15,AESTATEW
- BALR R14,R15
- C R15,=F'28' Error if "File not found"
- BNE EXIERR not returned
- LA R1,OUTPLIST Get ADT for output disk
- L R15,VCADTLKP
- BALR R14,R15
- BNZ ROERR (should not happen due to STATE)
- LR R2,R1 Check disk is R/W
- USING ADTSECT,R2
- TM ADTFLG1,ADTFRW Is disk R/W?
- BZ ROERR No, give error
- DROP R2
- * Define output file WRBUF plist
- LA R0,1 R0 = 1 for initializing
- SR R15,R15 R15 = 0 for initializing
- MVC OUTCMMD(8),=CL8'WRBUF' Command name
- STH R15,WRUN1 Unused halfword
- L R1,=A(WRITBUFF) Buffer address
- ST R1,WRADDR
- ST R15,WRBUFLTH Buffer size (will be set)
- MVI WRFV,C'V' Record format
- TM FLAGS,MACBIN MacBinary input file
- BO KEEPVAR Yes, keep recfm V
- MVC WRBUFLTH(4),=F'128' Lrecl 128 and recfm F for
- MVI WRFV,C'F' MacBinary output
- KEEPVAR MVI WRFLAG,X'20' Plist flag
- STH R15,WRUN2 Unused halfword
- ST R15,WRUN3 Unused word
- ST R15,WRITEM Item number
- ST R0,WRITEC Item count
- ST R15,WRWP Write and read pointers
- ST R15,WRRP
- INITDONE EQU * Ready to process files
- XC HDREC(128),HDREC Initialize header info.
- XC CHRTOTAL(4),CHRTOTAL Initialize count of characters
- TM FLAGS,MACBIN Separate processing for MacBinary
- BO BINPROC file format
- *
- * Read BinHex file to define file header info
- *
- LA R1,CVCNT0 Reset left over bit
- ST R1,BINXTADR processing
- MVI CMPCNT,0 Reset compression count
- XC BINLEN(4),BINLEN Reset count for BINBUFF
- XC CRCVAL(2),CRCVAL Reset CRC
- LA R0,1 R0 = length
- LA R1,HDFNLEN R1 -> buffer
- BAL R14,GETSTR Get length of filename
- BAL R14,CRCCALC Include in CRC
- SR R1,R1 Get length in R1
- IC R1,HDFNLEN
- LTR R1,R1 Skip getting name if zero
- BZ NONAME
- C R1,=F'63' If >63, use 63
- BNH FNLENOK
- L R1,=F'63'
- FNLENOK LR R0,R1 R0 = length
- LA R1,HDFN R1 -> buffer
- BAL R14,GETSTR Get filename
- BAL R14,CRCCALC Include in CRC
- NONAME LA R0,1 R0 = length
- LA R1,HDVER R1 -> buffer
- BAL R14,GETSTR Get version byte
- BAL R14,CRCCALC Include in CRC
- LA R0,10 R0 = length
- LA R1,HDFTYP R1 -> buffer
- BAL R14,GETSTR Get type, creator, flag bytes
- BAL R14,CRCCALC Include in CRC
- LA R0,8 R0 = length
- LA R1,HDDATALN R1 -> buffer
- BAL R14,GETSTR Get lengths of forks
- BAL R14,CRCCALC Include in CRC
- LA R0,2 R0 = length
- L R1,=A(DATABUFF) R1 -> buffer
- BAL R14,GETSTR Get header CRC
- BAL R14,CRCCALC Include in CRC
- CLC CRCVAL(2),=H'0' Is final CRC 0?
- BE HDCHKOK Yes, continue
- DMSERR LET=E,NUM=7,TEXT='''....................'': CRC error fX
- or BinHex header',SUB=(CHAR8A,IFN)
- MVI RTNCODE+3,44 Set RC = 44
- B CMSRTN Return to caller
- SPACE
- HDCHKOK EQU * HQX header successfully read
- CLI OPRCODE,C'V' Conversion wanted?
- BNE HDDESC No, check for description
- LA R1,HDREC Output header record
- BAL R14,WR128
- B CHKDATA Ready for data fork
- SPACE
- HDDESC CLI OPRCODE,C'D' Description wanted?
- BNE CHKDATA No, ready for data fork
- TM FLAGS2,EXECVAR Header info. wanted in vars.?
- BO HDVAR1
- BAL R14,TYPEHDR Type header description
- B CHKDATA Ready for data fork
- SPACE
- HDVAR1 BAL R14,VARHDR Return info. in vars.
- CHKDATA EQU * Check data fork
- ICM R3,B'1111',HDDATALN Get data fork length
- LR R4,R3 R4 = number of 128-byte pieces
- SRL R4,7
- LR R5,R4 R5 = bytes for all pieces
- SLL R5,7
- SR R3,R5 R3 = bytes left over
- LA R0,128 R0 = byte count
- L R1,=A(DATABUFF) R1 -> buffer
- XC CRCVAL(2),CRCVAL Reset CRC
- LTR R4,R4 Any pieces to read?
- BNP DCHKLEFT No, skip loop
- DCHKLP EQU * Loop to read 128-byte pieces
- BAL R14,GETSTR Read 128 bytes
- BAL R14,CRCCALC Include in CRC
- CLI OPRCODE,C'V' Conversion wanted?
- BNE DCHKNXT No, continue
- BAL R14,WR128 Write data block
- DCHKNXT BCT R4,DCHKLP Repeat for all pieces
- DCHKLEFT LTR R3,R3 Any bytes left?
- BNP DCHKEND No, compare CRC
- XC 0(128,R1),0(R1) Initialize buffer
- LR R0,R3 Length = bytes left
- BAL R14,GETSTR Read bytes
- BAL R14,CRCCALC Include in CRC
- CLI OPRCODE,C'V' Conversion wanted?
- BNE DCHKEND No, continue
- BAL R14,WR128 Write data block
- DCHKEND LA R0,2 Get CRC
- BAL R14,GETSTR
- BAL R14,CRCCALC Include CRC
- CLC CRCVAL(2),=H'0' Is result zero?
- BE CHKRSC Yes, check resource fork
- DMSERR LET=E,NUM=8,TEXT='''....................'': CRC error fX
- or BinHex data fork',SUB=(CHAR8A,IFN)
- MVI RTNCODE+3,44 Set RC = 44
- B CMSRTN Return to caller
- SPACE
- CHKRSC EQU * Check resource fork
- ICM R3,B'1111',HDRSCLN Get resource fork length
- LR R4,R3 R4 = number of 128-byte pieces
- SRL R4,7
- LR R5,R4 R5 = bytes for all pieces
- SLL R5,7
- SR R3,R5 R3 = bytes left over
- LA R0,128 R0 = byte count
- L R1,=A(DATABUFF) R1 -> buffer
- XC CRCVAL(2),CRCVAL Reset CRC
- LTR R4,R4 Any pieces to read?
- BNP RCHKLEFT No, skip loop
- RCHKLP EQU * Loop to read 128-byte pieces
- BAL R14,GETSTR Read 128 bytes
- BAL R14,CRCCALC Include in CRC
- CLI OPRCODE,C'V' Conversion wanted?
- BNE RCHKNXT No, continue
- BAL R14,WR128 Write data block
- RCHKNXT BCT R4,RCHKLP Repeat for all pieces
- RCHKLEFT LTR R3,R3 Any bytes left?
- BNP RCHKEND No, compare CRC
- XC 0(128,R1),0(R1) Initialize buffer
- LR R0,R3 Length = bytes left
- BAL R14,GETSTR Read bytes
- BAL R14,CRCCALC Include in CRC
- CLI OPRCODE,C'V' Conversion wanted?
- BNE RCHKEND No, continue
- BAL R14,WR128 Write data block
- RCHKEND LA R0,2 Get CRC
- BAL R14,GETSTR
- BAL R14,CRCCALC Include CRC
- CLC CRCVAL(2),=H'0' Is result 0?
- BNE RCHKERR No, give error
- RSCDONE EQU * BinHex code continues here
- CLI OPRCODE,C'D' Describe specified?
- BE DESCEND Yes, finish description
- CLI OPRCODE,C'C' Check specified?
- BNE CMSRTN No, ready to return
- CLI REGSAVE+4,X'0B' Called from command line?
- BNE CMSRTN No, ready to return
- L R8,=A(DATABUFF) R8 -> work buffer
- LINEDIT TEXT='''....................'': No errors detected', X
- SUB=(CHAR8A,IFN),BUFFA=(R8),DISP=NONE,RENT=NO
- BAL R14,TYPEDESC Type or stack line
- B CMSRTN
- SPACE
- DESCEND EQU * End file description
- L R8,=A(DATABUFF) R8 -> work buffer
- L R0,CHRTOTAL R0 = character count
- TM FLAGS2,EXECVAR Data in EXEC variables?
- BZ ENDTEXT No, do text
- L R1,=A(AVAR13) R1 -> CHARCNT string data
- LR R2,R1 Save R1 across NUMTOSTR
- LA R1,1(R8) R1 -> buffer for number
- BAL R14,NUMTOSTR Convert to string
- STC R0,0(R8) Store string length
- LR R1,R2 Restore R1 for SETVAR
- BAL R14,SETVAR Define stem.RESCSIZE
- L R4,CPS Was rate specified?
- LTR R4,R4 (Check if non-zero)
- BZ CMSRTN No, ready to return
- SR R5,R5 R5 = message length
- LA R6,1(R8) R6 -> next byte
- B TIMEMSG Join code for time estimate
- SPACE
- ENDTEXT MVC 1(17,R8),=C'Character count: ' Copy start of message
- LA R5,17 R5 = message length
- LA R6,1(R5,R8) R6 -> next byte
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store number in string form
- AR R5,R0 Update length and address
- AR R6,R0
- MVI 0(R6),C'.' Append period
- LA R5,1(R5) Update length and address
- LA R6,1(R6)
- STC R5,0(R8) Store length for TYPEDESC
- L R4,CPS Was rate specified?
- LTR R4,R4 (Check if non-zero)
- BZ RATEMSG No, ready to type message
- BCTR R6,0 R6 -> ending period
- MVC 0(2,R6),=C' (' Replace by blank, paren
- LA R5,1(R5) Adjust length for blank, paren
- LA R6,2(R6) R6 -> next byte
- TIMEMSG SR R2,R2 R2, R3 = character count
- L R3,CHRTOTAL
- DR R2,R4 Divide to get seconds in R3
- SRL R4,1 R4 = half of divisor
- CR R2,R4 Remainder more than half?
- BNH KEEPSEC No, keep seconds
- A R3,=F'1' Else add one second
- KEEPSEC SR R2,R2 R2, R3 = seconds
- D R2,=F'60' R2 = secs., R3 = mins.
- LR R4,R2 Save seconds in R4
- SR R2,R2 R2, R3 = minutes
- D R2,=F'60' R2 = minutes, R3 = hours
- LTR R0,R3 Any hours?
- BZ INCMIN No, ready for minutes
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store string there
- AR R5,R0 Adjust length and address
- AR R6,R0
- C R3,=F'1' Just one hour?
- BE ONEHOUR Yes, special case
- MVC 0(8,R6),=C' hours, ' Append text
- LA R5,8(R5) Adjust length and address
- LA R6,8(R6)
- B INCMIN Ready for minutes
- SPACE
- ONEHOUR MVC 0(7,R6),=C' hour, ' Append text
- LA R5,7(R5) Adjust length and address
- LA R6,7(R6)
- INCMIN LTR R0,R2 Any minutes?
- BZ INCSEC No, ready for seconds
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store string there
- AR R5,R0 Adjust length and address
- AR R6,R0
- C R2,=F'1' Just one minute?
- BE ONEMIN Yes, special case
- MVC 0(10,R6),=C' minutes, ' Append text
- LA R5,10(R5) Adjust length and address
- LA R6,10(R6)
- B INCSEC Ready for minutes
- SPACE
- ONEMIN MVC 0(9,R6),=C' minute, ' Append text
- LA R5,9(R5) Adjust length and address
- LA R6,9(R6)
- INCSEC LR R0,R4 R0 = number to convert
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store string there
- AR R5,R0 Adjust length and address
- AR R6,R0
- C R4,=F'1' Just one second?
- BE ONESEC Yes, special case
- MVC 0(12,R6),=C' seconds at ' Append text
- LA R5,12(R5) Adjust length and address
- LA R6,12(R6)
- B ENDTIME Ready to use text
- SPACE
- ONESEC MVC 0(11,R6),=C' second at ' Append text
- LA R5,11(R5) Adjust length and address
- LA R6,11(R6)
- ENDTIME L R0,CPS R0 = number to convert
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store string there
- AR R5,R0 Adjust length and address
- AR R6,R0
- TM FLAGS2,EXECVAR Is this for EXEC data
- BO TIMEVAR Yes, end differently
- MVC 0(6,R6),=C' cps).' Append text
- LA R5,6(R5) Update length
- STC R5,0(R8) Store new length for TYPEDESC
- RATEMSG BAL R14,TYPEDESC Type or stack line
- B CMSRTN
- SPACE
- TIMEVAR MVC 0(4,R6),=C' cps' Append text
- LA R5,4(R5) Update length
- STC R5,0(R8) Store new length for TYPEDESC
- L R1,=A(AVAR14) R1 -> TIMEEST string data
- BAL R14,SETVAR Define stem.TIMEEST
- B CMSRTN Ready to return
- SPACE
- RCHKERR DMSERR LET=E,NUM=9,TEXT='''....................'': CRC error fX
- or BinHex resource fork',SUB=(CHAR8A,IFN)
- MVI RTNCODE+3,44 Set RC = 44
- B CMSRTN Return to caller
- SPACE
- BINPROC EQU * Process MacBinary file
- BAL R14,GETLINE Read 128-byte header record
- LTR R15,R15 Check for EOF (strange)
- BNZ GSEOF Use error code in GETSTR
- L R2,=A(READBUFF) R2 -> I/O buffer
- MVC HDREC(128),0(R2) Copy data to header area
- CLI OPRCODE,C'V' Conversion wanted?
- BNE BINHDESC No, check for description
- * Initialize for HQX output:
- L R1,=A(HQXMSG) R1 -> initial message line
- L R2,=A(WRITBUFF) R2 -> output buffer
- MVC 0(HQXMSGL,R2),0(R1) Copy message to buffer
- LA R1,HQXMSGL Get message length
- ST R1,WRLEN Store as line length
- BAL R14,HQXLINE Output line to file
- MVI 0(R2),C' ' Output one blank
- LA R1,1 Length = 1
- ST R1,WRLEN
- BAL R14,HQXLINE Write blank line
- MVI 0(R2),C':' Initialize buffer with colon
- ST R1,WRLEN
- XC EXPLEN(4),EXPLEN Zero length for EXPBUFF
- MVI CMPMODE,0 Initial compression mode
- * Output HQX header data:
- XC CRCVAL(2),CRCVAL Reset CRC
- SR R2,R2 Get length of filename
- IC R2,HDFNLEN
- LA R0,1(R2) R0 = length with length byte
- LA R1,HDFNLEN R1 -> length
- BAL R14,HQXPUT Output to HQX file
- BAL R14,CRCCALC Include in CRC
- LA R0,1 R0 = 1 for version byte
- LA R1,HDVER R1 -> version byte
- BAL R14,HQXPUT Output version byte
- BAL R14,CRCCALC Include in CRC
- ICM R2,B'0011',HDFLAGS Save flag bits
- NC HDFLAGS(2),=X'F800' For HQX, 'and' with X'F800'
- LA R0,10 R0 = 10 (4+4+2)
- LA R1,HDFTYP R1 -> type
- BAL R14,HQXPUT Output type, creator, flags
- BAL R14,CRCCALC Include in CRC
- STCM R2,B'0011',HDFLAGS Restore original flag bits
- LA R0,8 R0 = 8 (4+4)
- LA R1,HDDATALN R1 -> lengths
- BAL R14,HQXPUT Output data and resource lengths
- BAL R14,CRCCALC Include in CRC
- LA R0,2 Include X'0000' in CRC
- LA R1,=H'0'
- BAL R14,CRCCALC
- LA R0,2 R0 = length of CRC
- LA R1,CRCVAL R1 -> CRC
- BAL R14,HQXPUT End header with CRC
- B BINDATA Ready for data fork
- SPACE
- BINHDESC CLI OPRCODE,C'D' Description wanted?
- BNE BINDATA No, ready for data fork
- TM FLAGS2,EXECVAR Header info. wanted in vars.?
- BO HDVAR2
- BAL R14,TYPEHDR Type header description
- B BINDATA Ready for data fork
- SPACE
- HDVAR2 BAL R14,VARHDR Return info. in vars.
- BINDATA EQU * Process BinHex data fork
- ICM R3,B'1111',HDDATALN Get data fork length
- LR R4,R3 R4 = number of 128-byte records
- SRL R4,7
- LR R5,R4 R5 = bytes for all records
- SLL R5,7
- SR R3,R5 R3 = bytes left over
- LA R0,128 R0 = byte count
- L R1,=A(READBUFF) R1 -> buffer
- XC CRCVAL(2),CRCVAL Reset CRC
- LTR R4,R4 Any entire records to read?
- BNP BINDLEFT No, skip loop
- BINDLP EQU * Loop to read 128-byte records
- BAL R14,GETLINE Read 128-byte record
- LTR R15,R15 Check for EOF
- BNZ GSEOF Use error code in GETSTR
- CLI OPRCODE,C'V' Conversion wanted?
- BNE BINDNXT No, continue
- BAL R14,HQXPUT Write data block
- BAL R14,CRCCALC Include in CRC
- BINDNXT BCT R4,BINDLP Repeat for all pieces
- BINDLEFT LTR R3,R3 Any bytes left?
- BNP BINDEND No, check for writing CRC
- BAL R14,GETLINE Read 128-byte record
- LTR R15,R15 Check for EOF
- BNZ GSEOF Use error code in GETSTR
- CLI OPRCODE,C'V' Conversion wanted?
- BNE BINDEND No, skip writing data
- LR R0,R3 Use remaining bytes length
- BAL R14,HQXPUT Write data block
- BAL R14,CRCCALC Include in CRC
- BINDEND CLI OPRCODE,C'V' Conversion wanted?
- BNE BINRSC No, ready for resource fork
- LA R0,2 Include X'0000' in CRC
- LA R1,=H'0'
- BAL R14,CRCCALC
- LA R0,2 R0 = size of CRC
- LA R1,CRCVAL R1 -> CRC
- BAL R14,HQXPUT Output data fork CRC
- BINRSC EQU * Process BinHex resource fork
- ICM R3,B'1111',HDRSCLN Get resource fork length
- LR R4,R3 R4 = number of 128-byte records
- SRL R4,7
- LR R5,R4 R5 = bytes for all records
- SLL R5,7
- SR R3,R5 R3 = bytes left over
- LA R0,128 R0 = byte count
- L R1,=A(READBUFF) R1 -> buffer
- XC CRCVAL(2),CRCVAL Reset CRC
- LTR R4,R4 Any entire records to read?
- BNP BINRLEFT No, skip loop
- BINRLP EQU * Loop to read 128-byte records
- BAL R14,GETLINE Read 128-byte record
- LTR R15,R15 Check for EOF
- BNZ GSEOF Use error code in GETSTR
- CLI OPRCODE,C'V' Conversion wanted?
- BNE BINRNXT No, continue
- BAL R14,HQXPUT Write resource block
- BAL R14,CRCCALC Include in CRC
- BINRNXT BCT R4,BINRLP Repeat for all pieces
- BINRLEFT LTR R3,R3 Any bytes left?
- BNP BINREND No, check for writing CRC
- BAL R14,GETLINE Read 128-byte record
- LTR R15,R15 Check for EOF
- BNZ GSEOF Use error code in GETSTR
- CLI OPRCODE,C'V' Conversion wanted?
- BNE BINREND No, skip writing data
- LR R0,R3 Use remaining bytes length
- BAL R14,HQXPUT Write resource block
- BAL R14,CRCCALC Include in CRC
- BINREND CLI OPRCODE,C'V' Conversion wanted?
- BNE RSCDONE No, join common end code
- LA R0,2 Include X'0000' in CRC
- LA R1,=H'0'
- BAL R14,CRCCALC
- LA R0,2 R0 = size of CRC
- LA R1,CRCVAL R1 -> CRC
- BAL R14,HQXPUT Output data fork CRC
- L R0,=F'-1' R0 = -1 for cleanup
- BAL R14,HQXPUT HQXPUT final cleanup call
- * append final colon
- L R1,WRLEN Room for colon in buffer?
- C R1,=F'64' Yes, if length < 64
- BL BINADDC
- BAL R14,HQXLINE Else write 64 bytes to file
- XC WRLEN(4),WRLEN and reset length
- BINADDC L R2,WRLEN R2 = no. of bytes in WRITBUFF
- L R1,=A(WRITBUFF) R1 -> start of buffer
- LA R3,0(R1,R2) R3 -> next location
- MVI 0(R3),C':' Store ending colon
- LA R2,1(R2) Store new length
- ST R2,WRLEN
- BAL R14,HQXLINE Output final line
- B RSCDONE Join common code
- EJECT
- *
- * HQXPUT - Apply HQX compression algorithm to binary data, and call
- * HQXEXP to expand up to 48 bytes of binary to up to 64 bytes
- * of printable characters. At entry R0 is the number of bytes
- * to process, and R1 contains their address. HQXPUT is called
- * with R0 < 0 for final cleanup.
- *
- HQXPUT DS 0H
- LTR R0,R0 Just return if zero bytes
- BZR R14
- STM R0,R15,HPUTSAVE Save registers
- LR R2,R0 R2 = count for BCT
- * R1 -> current byte
- SR R3,R3 R3 = current CMPMODE
- IC R3,CMPMODE
- SR R4,R4 R4 = current HCMPCHAR
- IC R4,HCMPCHAR
- SR R5,R5 R5 = current CMPCOUNT
- IC R5,CMPCOUNT
- L R9,EXPLEN R9 = output length
- L R8,=A(EXPBUFF) R8 -> next output byte
- LA R8,0(R8,R9)
- LTR R2,R2 Ready for main loop if R2 > 0
- BP HPUTLP
- * Else final cleanup call
- CLI CMPMODE,0 Done if mode = 0
- BE HCLEND
- SR R1,R1 Set byte address to 0
- LA R2,1 Set BCT count to 1
- SR R6,R6 Get character in R6
- IC R6,HCMPCHAR
- SR R7,R7 Get count in R7
- IC R7,CMPCOUNT
- B HOUT Enter loop at output code
- SPACE
- HPUTLP EQU * Loop to process each character
- LTR R3,R3 Check for mode 1
- BNZ HPUT1
- * Else mode 0:
- HPUT0 EQU * Mode 0: initial mode
- IC R4,0(R1) Save current character
- LA R5,1 Set count to 1
- LA R3,1 Set mode to 1
- B HPUTNXT Ready for next byte
- SPACE
- HPUT1 EQU * Mode 1: checking for comp.
- CLM R4,B'0001',0(R1) New char. the same as prev.?
- BNE HDIFF No, go handle
- LA R5,1(R5) Increment count
- C R5,=F'255' Done if < 255
- BL HPUTNXT
- LR R6,R4 R6 = char. to output
- LR R7,R5 R7 = count
- SR R3,R3 Mode = 0 (no prev. char.)
- B HOUT
- SPACE
- HDIFF EQU * New char. not same as prev.
- * Output previous character
- LR R6,R4 R6 = char. to output
- LR R7,R5 R7 = count to output
- IC R4,0(R1) Save current character
- LA R5,1 Set count to 1
- HOUT EQU * Char. in R6, count in R7
- LTR R7,R7 Done if count = 0
- BZ HPUTNXT
- STC R6,0(R8) Append byte to buffer
- LA R8,1(R8) Increment pointer
- LA R9,1(R9) Increment count
- C R9,=F'48' Buffer full?
- BL HOUT2 No, check for X'90'
- ST R9,EXPLEN Store length for HQXEXP
- BAL R14,HQXEXP Call expansion routine
- L R8,=A(EXPBUFF) Reset pointer
- SR R9,R9 Reset count
- HOUT2 CLM R6,B'0001',=X'90' Is character X'90'?
- BNE HOUT3 No, check for repetition
- MVI 0(R8),0 Append zero byte
- LA R8,1(R8) Increment pointer
- LA R9,1(R9) Increment count
- C R9,=F'48' Buffer full?
- BL HOUT3 No, check for repetition
- ST R9,EXPLEN Store length for HQXEXP
- BAL R14,HQXEXP Call expansion routine
- L R8,=A(EXPBUFF) Reset pointer
- SR R9,R9 Reset count
- HOUT3 BCTR R7,0 Decrement count
- C R7,=F'2' If < 2 more, output w/o comp.
- BL HOUT
- * else output X'90', count
- MVI 0(R8),X'90' Append X'90'
- LA R8,1(R8) Increment pointer
- LA R9,1(R9) Increment count
- C R9,=F'48' Buffer full?
- BL HOUT4 No, ready for count
- ST R9,EXPLEN Store length for HQXEXP
- BAL R14,HQXEXP Call expansion routine
- L R8,=A(EXPBUFF) Reset pointer
- SR R9,R9 Reset count
- HOUT4 LA R7,1(R7) Restore original byte count
- STC R7,0(R8) Append byte count
- LA R8,1(R8) Increment pointer
- LA R9,1(R9) Increment count
- C R9,=F'48' Buffer full?
- BL HPUTNXT No, all done
- ST R9,EXPLEN Store length for HQXEXP
- BAL R14,HQXEXP Call expansion routine
- L R8,=A(EXPBUFF) Reset pointer
- SR R9,R9 Reset count
- HPUTNXT LA R1,1(R1) R1 -> next byte
- BCT R2,HPUTLP Decrement count and repeat
- L R2,HPUTSAVE Get original R0
- LTR R2,R2 If <0, finish cleanup
- BM HCLEND
- ST R9,EXPLEN Store EXPBUFF length
- STC R3,CMPMODE Store CMPMODE
- STC R4,HCMPCHAR Store HCMPCHAR
- STC R5,CMPCOUNT Store CMPCOUNT
- HPUTRTN LM R0,R15,HPUTSAVE Restore registers
- BR R14 Return to caller
- SPACE
- HCLEND EQU * Output bytes left in EXPBUFF
- ST R9,EXPLEN Store length for HQXEXP
- C R9,=F'48' Check for zeros to add
- BE HNOZERO None if buffer full
- MVI 0(R8),0 Add one zero
- LA R8,1(R8)
- C R9,=F'47' Room for another?
- BE HNOZERO No, ready to output
- MVI 0(R8),0 Add another null
- HNOZERO BAL R14,HQXEXP Call expansion routine
- B HPUTRTN Ready to return
- SPACE
- HPUTSAVE DS 8D Local save area
- EJECT
- *
- * HQXEXP - Expand data in EXPBUFF to 6 bits in each byte. The length
- * is used from EXPLEN, and is assumed to not exceed 48.
- * Expanded data is translated and moved to WRITBUFF. HQXLINE
- * is called to output WRITBUFF as necessary.
- *
- HQXEXP STM R0,R15,HEXPSAVE Save registers
- SR R2,R2 R2, R3 = size of EXPBUFF data
- L R3,EXPLEN
- LTR R3,R3 If zero, just return
- BZ HEXPRTN
- D R2,=F'3' Divide to get 3-byte pieces
- LTR R2,R2 Check for any remainder
- BZ HNORM If none, keep count
- LA R0,1(R3) Piece count = quotient+1
- SLL R3,2 Length = quotient*4
- LA R3,1(R2,R3) + remainder + 1
- LR R2,R0 Copy piece count to R2
- B HCNT Continue with these counts
- SPACE
- HNORM LR R2,R3 R2 = count of pieces for BCT
- SLL R3,2 R3 = output length (count*4)
- HCNT L R4,=A(EXPBUFF) R4 -> start of input
- LA R5,HEXPBUFF R5 -> start of output
- HEXPLP EQU * Loop to expand pieces
- ICM R7,B'1110',0(R4) Get all 24 bits in R7
- SR R6,R6 Get first 6 bits in R6
- SLDL R6,6
- STC R6,0(R5) Store first result byte
- SR R6,R6 Repeat for 2nd byte
- SLDL R6,6
- STC R6,1(R5)
- SR R6,R6 Repeat for 3rd byte
- SLDL R6,6
- STC R6,2(R5)
- SR R6,R6 Repeat for 4th byte
- SLDL R6,6
- STC R6,3(R5)
- LA R4,3(R4) Increment input pointer
- LA R5,4(R5) Increment output pointer
- BCT R2,HEXPLP Repeat for piece count
- BCTR R3,0 Get length-1 for execute
- L R4,=A(BINTOASC) R4 -> binary-to-ASCII table
- EX R3,HEXPTR Convert binary to ASCII
- L R4,FRASCADR R4 -> ASCII-to-EBCDIC table
- EX R3,HEXPTR Convert ASCII to EBCDIC
- LA R3,1(R3) Restore original length
- LA R2,HEXPBUFF R2 -> first byte
- LA R5,64 R5 = bytes left in WRITBUFF
- S R5,WRLEN
- CR R3,R5 Will all bytes fit?
- BNH HEXWRCPY Yes, copy into buffer
- L R4,=A(WRITBUFF) R4 -> next output location
- A R4,WRLEN
- BCTR R5,0 R5 = length for EX
- EX R5,HEXPMVC Fill output buffer
- LA R4,64 Store new length
- ST R4,WRLEN
- BAL R14,HQXLINE Output buffer to file
- XC WRLEN(4),WRLEN Reset length
- LA R5,1(R5) Get actual count moved
- SR R3,R5 R3 = bytes still to move
- LA R2,0(R2,R5) R2 -> next byte to move
- HEXWRCPY L R4,=A(WRITBUFF) R4 -> next output location
- A R4,WRLEN
- BCTR R3,0 R3 = length for EX
- EX R3,HEXPMVC Move bytes to output buffer
- L R4,WRLEN Update buffer size
- LA R4,1(R3,R4)
- ST R4,WRLEN
- C R4,=F'64' Is buffer full now?
- BNE HEXPRTN No, ready to return
- BAL R14,HQXLINE Output full buffer
- XC WRLEN(4),WRLEN Reset buffer length
- HEXPRTN LM R0,R15,HEXPSAVE Restore registers
- BR R14 Return to caller
- SPACE
- HEXPSAVE DS 8D Local save area
- HEXPBUFF DS 8D Local buffer for expansion
- HEXPTR TR HEXPBUFF(*-*),0(R4)
- HEXPMVC MVC 0(*-*,R4),0(R2)
- EJECT
- *
- * HQXLINE - Write contents of WRITBUFF to output file. The current
- * length of the data in WRITBUFF is given in WRITLEN.
- * Returns to caller if no error; otherwise types an error
- * message and returns directly to CMS.
- *
- HQXLINE DS 0H
- STM R0,R15,HQXLSAVE Save registers
- L R2,WRITEM Increment line number
- LA R2,1(R2)
- ST R2,WRITEM
- OI FLAGS,WROPEN Remember file is open
- MVC WRBUFLTH(4),WRLEN Set line length from buffer size
- LA R1,OUTPLIST R1 -> PLIST
- L R15,AWRBUF R15 -> WRBUF entry
- BALR R14,R15 Call WRBUF
- BZ HQXLRET If ok, ready to return
- LR R2,R15 Copy error code to R2
- DMSERR LET=S,NUM=105, X
- TEXT='Error ''..'' writing file ''....................''X
- on disk',SUB=(DEC,(R2),CHAR8A,OFN),RENT=NO
- LA R2,100(R2) Set RC = 1nn
- ST R2,RTNCODE Set code to return
- B CMSRTN Direct return to CMS
- SPACE
- HQXLRET LM R0,R15,HQXLSAVE Restore registers
- BR R14 Return to caller
- SPACE
- HQXLSAVE DS 8D Local save area
- EJECT
- *
- * GETSTR - Fill buffer with bytes from input file. At entry,
- * R0 contains the buffer size and R1 contains the buffer
- * address. If any errors occur, GETSTR generates an
- * error message and returns to CMS.
- *
- GETSTR DS 0H
- STM R0,R15,GSSAVE Save registers
- LR R4,R0 R4 = buffer size
- LR R5,R1 R5 -> buffer
- GSAGAIN LTR R4,R4 Buffer size = 0?
- BZ GSRTN If so, just return
- CLI CMPCNT,0 Compressed data to return?
- BNE GSUSECMP Yes, go use it
- L R6,BINLEN R6 = count of bytes left
- L R7,=A(BINBUFF) R7 -> next byte
- A R7,BINOFF
- LTR R6,R6 Any bytes left?
- BP GSUSEBIN Yes, go use them
- MVC GSPREV(1),BINLAST Save last byte from current line
- BAL R14,GTBINLIN Read more binary data
- LTR R15,R15 Any error?
- BZ GSAGAIN No, use data
- B GSEOF Else return EOF
- SPACE
- GSUSEBIN EQU * Process data in BINBUFF
- LA R1,0(R6,R7) R1 -> past last byte
- LR R3,R6 R3 = length-1 for TRT
- BCTR R3,0
- L R8,=A(CMPTAB) R8 -> TRT table
- EX R3,CMPTRT Scan for X'90' in BINBUFF
- SR R1,R7 R1 = length before X'90'
- BZ GSCMPINI If none, set up for compression
- NI FLAGS,255-X90DATA X90 data byte no longer current
- CR R1,R4 Longer than needed?
- BNH GSMVDATA No, keep length
- LR R1,R4 Else reduce to length needed
- GSMVDATA BCTR R1,0 Decrement length for EX
- EX R1,DATAMVC Move data to caller's buffer
- LA R1,1(R1) Restore actual length
- SR R4,R1 Decrement buffer size
- LA R5,0(R1,R5) Increment buffer address
- L R2,BINLEN Decrement binary length
- SR R2,R1
- ST R2,BINLEN
- L R2,BINOFF Increment binary offset
- AR R2,R1
- ST R2,BINOFF
- B GSAGAIN Check for more to do
- SPACE
- GSCMPINI EQU * R7 -> X'90'
- * Get compression character
- TM FLAGS,X90DATA Have character from last X'90'?
- BO USEX90 Yes, use it
- L R1,BINOFF Is X'90' at start of line
- LTR R1,R1 If so, use byte from previous line
- BZ USEPREV
- LR R1,R7 Else use previous byte on line
- BCTR R1,0 R1 -> byte to use
- B STCMPCHR
- SPACE
- USEX90 LA R1,X90CHAR R1 -> byte from last X90
- B STCMPCHR
- SPACE
- USEPREV LA R1,GSPREV R1 -> byte to use
- STCMPCHR MVC CMPCHAR(1),0(R1) Store byte to replicate
- OI FLAGS,X90DATA Set flag for X90 data
- MVC X90CHAR(1),0(R1) Save X90 data byte
- C R6,=F'1' Is count available after X'90'?
- BNH GSRDCNT No, go read it
- MVC CMPCNT(1),1(R7) Store compression count
- L R2,BINOFF Increment binary offset
- LA R2,2(R2)
- ST R2,BINOFF
- L R2,BINLEN Decrement binary length
- BCTR R2,0
- BCTR R2,0
- ST R2,BINLEN
- B CHKCMP Ready to check what we have
- SPACE
- GSRDCNT BAL R14,GTBINLIN Read more binary data
- LTR R15,R15 Any error?
- BNZ GSEOF Yes, return EOF
- L R6,BINLEN Update R6, R7 for new read
- L R7,=A(BINBUFF)
- A R7,BINOFF
- MVC CMPCNT(1),0(R7) Store compression count
- L R2,BINOFF Increment binary offset
- LA R2,1(R2)
- ST R2,BINOFF
- L R2,BINLEN Decrement binary length
- BCTR R2,0
- ST R2,BINLEN
- CHKCMP CLI CMPCNT,0 New count = 0?
- BNE GSDECCMP No, adjust count to be length
- MVI X90CHAR,X'90' Data byte is now X'90'
- MVI 0(R5),X'90' Return X'90'
- BCTR R4,0 Decrement buffer size
- LA R5,1(R5) Increment buffer pointer
- B GSAGAIN See if more to do
- SPACE
- GSDECCMP SR R1,R1 Get count in R1
- IC R1,CMPCNT
- BCTR R1,0 Decrement to get replication count
- STC R1,CMPCNT
- LTR R1,R1 If zero, start again
- BNP GSAGAIN
- GSUSECMP SR R1,R1 R1 = compression count
- IC R1,CMPCNT
- LR R2,R1 Save in R2
- CR R1,R4 Count bigger than buffer size?
- BNH CMPCPY No, keep count
- LR R1,R4 Else reduce to buffer size
- CMPCPY SR R2,R1 R2 = remaining count
- STC R2,CMPCNT Store remaining count
- LR R8,R1 Save count in R8
- LR R0,R5 R0 -> destination
- * R1 = destination length
- SR R2,R2 R2 -> source (none)
- SR R3,R3 R3 = source length (zero)
- ICM R3,B'1000',CMPCHAR Pad char. = compression char.
- MVCL R0,R2 Store duplicated characters
- SR R4,R8 Decrement buffer size
- LA R5,0(R5,R8) Increment buffer pointer
- B GSAGAIN Check for more to do
- SPACE
- GSRTN LM R0,R15,GSSAVE Restore registers
- BR R14 Return to caller
- SPACE
- GSEOF DMSERR NUM=6,LET=E, X
- TEXT='Unexpected end-of-file reading ''.................X
- ...''',SUB=(CHAR8A,IFN)
- MVI RTNCODE+3,36 CMS RC = 36
- B CMSRTN
- SPACE
- GSSAVE DS 8D Local save area
- CMPTRT TRT 0(*-*,R7),0(R8) TRT for X'90'
- DATAMVC MVC 0(*-*,R5),0(R7) Move binary data to buffer
- GSPREV DS 1X Last byte from previous line
- X90CHAR DS 1X Data byte for last X'90'
- EJECT
- *
- * GTBINLIN - Convert data in READBUFF to binary data in BINBUFF
- * (HQX files only). The length is returned in BINLEN.
- * Returns R15=0 (ok) or R15=12 (eof).
- *
- GTBINLIN DS 0H
- STM R0,R15,GBSAVE Save registers
- GBAGAIN BAL R14,GETLINE Get more data from file
- ST R15,GBSAVE+60 Store return code
- LTR R15,R15 Return if non-zero
- BNZ GBRET
- XC BINOFF(4),BINOFF Reset offset for reading result
- L R1,=A(READBUFF) R1 -> first byte
- A R1,RDOFF
- L R2,RDLGTH R2 = length
- L R3,=A(BINBUFF) R3 -> output buffer
- SR R4,R4 R4 = output length
- LA R5,CVCNT0 R5 = addr. for checking zero bits
- GBINILP EQU * Loop until no bits left over or EOF
- LTR R2,R2 Any bytes left?
- BZ GBEND No, ready to return
- C R5,BINXTADR No bits left over?
- BE GBGROUP Yes, do groups of bytes
- BAL R14,CVTBYTE Convert next byte
- STC R0,0(R3) Store output byte
- LA R3,1(R3) Increment address
- LA R4,1(R4) Increment length
- LA R1,1(R1) Increment pointer
- BCTR R2,0 Decrement length
- B GBINILP Repeat
- SPACE
- * Process groups of 8 input byte to get 6 binary bytes
- GBGROUP LR R5,R2 Get count of groups
- SRL R5,3 = byte count/8
- LTR R5,R5 Any groups?
- BZ GBFIN No, loop for any bytes left
- SR R8,R8 R8 = 0 for IC
- LA R0,1 R0 = 1 for increments
- GBGRLP EQU * Loop to process groups
- LA R9,8 R9 = byte count for loop
- GBG1LP EQU * Loop for 1 group
- IC R8,0(R1) Get new byte
- SLDL R6,6 Make room for new bits
- OR R7,R8 OR-in bits
- AR R1,R0 R1 -> next byte
- BCT R9,GBG1LP Repeat for 8 bytes
- S R2,=F'8' Decrement bytes left
- STCM R6,B'0011',0(R3) Store result bytes
- STCM R7,B'1111',2(R3)
- LA R3,6(R3) Increment output address
- LA R4,6(R4) Increment output length
- BCT R5,GBGRLP Loop for all groups
- * Loop to process any remaining bytes
- GBFIN LTR R2,R2 Any bytes left?
- BZ GBEND No, ready to return
- GBENDLP EQU * Loop to process remaining bytes
- BAL R14,CVTBYTE Convert next byte
- LTR R0,R0 Result byte returned?
- BM GBENDNXT No, skip saving byte
- STC R0,0(R3) Store output byte
- LA R3,1(R3) Increment address
- LA R4,1(R4) Increment length
- GBENDNXT LA R1,1(R1) Increment pointer
- BCT R2,GBENDLP
- SPACE
- * Return to caller
- GBEND LTR R4,R4 Non-zero length to return?
- BZ GBAGAIN No, read next line
- ST R4,BINLEN Store output length
- L R3,=A(BINBUFF) R4 -> last byte
- LA R3,0(R3,R4)
- BCTR R3,0
- MVC BINLAST(1),0(R3) Save in case part of compression
- GBRET LM R0,R15,GBSAVE Restore registers, RC in R15
- BR R14
- SPACE
- GBSAVE DS 8D Local save area
- EJECT
- *
- * CVTBYTE - Read next byte using address in R1 and any left over bits
- * in BINEXTRA. Return a new byte in R0, and set BINEXTRA
- * and BINXTADR as appropriate. Return R0=-1 if more bits
- * are needed to make a byte.
- *
- CVTBYTE DS 0H
- STM R0,R15,CVSAVE Save registers and RC
- L R2,BINXTADR Get addr. for processing
- BR R2 Branch for left over bits
- SPACE
- CVCNT0 EQU * No bits left over
- IC R3,0(R1) New bits in R3
- LA R1,CVCNT6 Set 6 bits left over
- ST R1,BINXTADR
- L R0,=F'-1' Return -1 in R0
- STC R3,BINEXTRA Store left over bits
- B CVRTN
- SPACE
- CVCNT6 EQU * 6 bits left from last time
- SR R2,R2 Left over bits in R2
- IC R2,BINEXTRA
- IC R3,0(R1) New bits in R3
- SLL R3,26 Make new bits most significant
- SLDL R2,2 Get new byte in R2
- SRL R3,28 Get left over bits in R3
- LA R1,CVCNT4 Set 4 bits left over
- ST R1,BINXTADR
- LR R0,R2 Return byte in R0
- STC R3,BINEXTRA Store left over bits
- B CVRTN Ready to return
- SPACE
- CVCNT4 EQU * 4 bits left from last time
- SR R2,R2 Left over bits in R2
- IC R2,BINEXTRA
- IC R3,0(R1) New bits in R3
- SLL R3,26 Make new bits most significant
- SLDL R2,4 Get new byte in R2
- SRL R3,30 Get left over bits in R3
- LA R1,CVCNT2 Set 2 bits left over
- ST R1,BINXTADR
- LR R0,R2 Return byte in R0
- STC R3,BINEXTRA Store left over bits
- B CVRTN Ready to return
- SPACE
- CVCNT2 EQU * 2 bits left from last time
- SR R2,R2 Left over bits in R2
- IC R2,BINEXTRA
- IC R3,0(R1) New bits in R3
- SLL R3,26 Make new bits most significant
- SLDL R2,6 Get new byte in R2
- LA R1,CVCNT0 Set 0 bits left over
- ST R1,BINXTADR
- LR R0,R2 Return byte in R0
- * B CVRTN Ready to return
- SPACE
- CVRTN LM R1,R15,CVSAVE+4 Restore all but result in R0
- BR R14 Return to caller
- SPACE
- CVSAVE DS 8D Local save area
- EJECT
- *
- * GETLINE - Read the next line of the input file into READBUFF.
- * The length is returned in RDLGTH and the starting
- * offset is returned in RDOFF. For HQX files, data is
- * returned between a starting colon in column one of a
- * line, and an ending colon. Also, data is translated
- * to six-bit binary.
- * Return R15=0 (ok) or R15=12 (eof).
- *
- GETLINE DS 0H
- STM R0,R15,GLSAVE Save registers
- GLAGAIN TM FLAGS,HQXEOF EOF set from last time?
- BO GLEOFRET Yes, return eof
- L R1,RDITEM Increment line number
- LA R1,1(R1)
- ST R1,RDITEM
- XC RDOFF(4),RDOFF Reset read offset
- OI FLAGS,RDOPEN Remember input file is open
- LA R1,INPLIST R1 -> PLIST
- L R15,ARDBUF R15 -> RDBUF entry
- BALR R14,R15 Call RDBUF
- ST R15,GLSAVE+60 Return RC in R15
- BZ GLRDOK RC 0 is normal
- C R15,=F'12' RC 12 is eof
- BE GLRET
- * Else unexpected error
- LR R2,R15 Copy error code to R2
- DMSERR LET=S,NUM=104, X
- TEXT='Error ''..'' reading file ''....................''X
- from disk',SUB=(DEC,(R2),CHAR8A,IFN),RENT=NO
- LA R2,100(R2) Set RC = 1nn
- ST R2,RTNCODE
- B CMSRTN Direct return to CMS
- SPACE
- GLRDOK CLC RDLGTH(4),=F'0' Any bytes read?
- BE GLAGAIN No (very strange); try again
- L R1,CHRTOTAL Increment character count
- A R1,RDLGTH
- ST R1,CHRTOTAL
- TM FLAGS,MACBIN If reading MacBinary, all done
- BO GLRET
- * For HQX file, adjust length to delete trailing blanks
- L R1,RDLGTH R1 = count for BCT
- L R2,=A(READBUFF) R2 -> last byte
- LA R2,0(R1,R2) R2 -> last byte
- BCTR R2,0
- GLTRLOOP EQU * Loop to truncate blanks
- CLI 0(R2),C' ' Found non-blank?
- BNE GLTREND Yes, done
- BCTR R2,0 R2 -> previous byte
- BCT R1,GLTRLOOP Repeat for line length
- B GLAGAIN If all blank, read next line
- SPACE
- GLTREND ST R1,RDLGTH Store adjusted line length
- * For HQX file, handle initial colon
- TM FLAGS,HQXCOLON Colon in previous line?
- BO GLHQXCNT Yes, continue
- L R2,=A(READBUFF) Does this line start with colon?
- CLI 0(R2),C':'
- BNE GLAGAIN No, try again
- OI FLAGS,HQXCOLON Remember have found colon
- BCTR R1,0 Decrement line length
- LTR R1,R1 Zero now?
- BZ GLAGAIN Yes, get next line
- ST R1,RDLGTH Store new length
- LA R2,1 Initial offset = 1
- ST R2,RDOFF
- * For HQX file, check for ending colon or invalid character
- GLHQXCNT L R3,=A(READBUFF) R3 -> first byte
- A R3,RDOFF
- L R4,RDLGTH R4 = length
- BCTR R4,0 Decrement length for EX
- SR R1,R1 Initialize R1 before TRT
- L R5,=A(VALIDTAB) R5 -> TRT table
- EX R4,HQXTRT Scan for invalid character
- BZ GLHQXTR Ready to translate if none
- OI FLAGS,HQXEOF Remember EOF for HQX file
- MVC EOFCHAR(1),0(R1) Save character we stopped at
- LA R2,1(R1) Save character position in line
- L R4,=A(READBUFF)
- SR R2,R4
- ST R2,EOFPOS
- SR R1,R3 R1 = new length
- ST R1,RDLGTH Store new length
- BNP GLEOFRET Return EOF if not positive
- * For HQX file, translate EBCDIC to 6-bit binary
- GLHQXTR L R1,RDLGTH R1 = length
- BCTR R1,0 Decrement for EX
- L R2,=A(READBUFF) R2 -> first byte
- A R2,RDOFF
- L R3,TOASCADR R3 -> EBCDIC-to-ASCII table
- EX R1,GLTR Translate data to ASCII
- L R3,=A(ASCTOBIN) R3 -> ASCII-to-binary table
- EX R1,GLTR Translate ASCII to binary
- * Return to caller
- GLRET LM R0,R15,GLSAVE Restore registers, RC in R15
- BR R14
- SPACE
- GLEOFRET CLI EOFCHAR,C':' Stopped at a colon?
- BNE GLBADCHR No, give error message
- LA R15,12 Else return normal eof
- LM R0,R14,GLSAVE
- BR R14
- SPACE
- GLBADCHR DMSERR LET=E,NUM=5,TEXT='Invalid character ''..'' in ''.......X
- .............'' at line .......... position ...', X
- RENT=NO,SUB=(CHARA,(EOFCHAR,1),CHAR8A,IFN,DECA,RDITEM,DEX
- CA,EOFPOS)
- MVI RTNCODE+3,36 Set RC = 36
- B CMSRTN Direct return to CMS
- SPACE
- GLSAVE DS 8D Local save area
- HQXTRT TRT 0(*-*,R3),0(R5) TRT to check valid characters
- GLTR TR 0(*-*,R2),0(R3) Translate to ASCII or binary
- EJECT
- *
- * WR128 - Write 128 bytes of data to a MacBinary output file.
- * At entry, R1 -> 128 bytes to be written.
- *
- WR128 DS 0H
- STM R0,R15,WRSAVE Save registers
- L R2,WRITEM Increment line number
- LA R2,1(R2)
- ST R2,WRITEM
- OI FLAGS,WROPEN Remember output file is open
- ST R1,WRADDR Store buffer address
- LA R1,OUTPLIST R1 -> PLIST
- L R15,AWRBUF R15 -> WRBUF entry
- BALR R14,R15 Call WRBUF
- BZ WRRET If ok, ready to return
- LR R2,R15 Copy error code to R2
- DMSERR LET=S,NUM=105, X
- TEXT='Error ''..'' writing file ''....................''X
- on disk',SUB=(DEC,(R2),CHAR8A,OFN),RENT=NO
- LA R2,100(R2) Set RC = 1nn
- ST R2,RTNCODE
- B CMSRTN Direct return to CMS
- SPACE
- WRRET LM R0,R15,WRSAVE Restore registers
- BR R14 Return to caller
- SPACE
- WRSAVE DS 8D Local save area
- EJECT
- *
- * CRCCALC - Update CRCVAL for a string. At entry, R0 = string length
- * and R1 -> string.
- *
- CRCCALC DS 0H
- STM R0,R15,CRCSAVE Save registers
- LTR R7,R0 R7 = BCT count
- BZ CRCRTN If zero, just return
- LR R6,R1 R6 -> first byte
- SR R3,R3 R3 = current CRC
- ICM R3,B'1100',CRCVAL (in msb)
- L R4,=V(XMDMTAB) R4 -> CRC table
- SR R5,R5 R5 = 0 for table entries
- CRCLOOP EQU * Loop for each character
- SR R2,R2 Shift CRC and get old
- SLDL R2,8 msb in R2
- ICM R3,B'0100',0(R6) Append new byte to CRC
- SLL R2,1 R2 = table offset
- LA R2,0(R2,R4) R2 -> table entry
- ICM R5,B'1100',0(R2) R5 = table entry
- XR R3,R5 update CRC
- LA R6,1(R6) R6 -> next byte
- BCT R7,CRCLOOP Repeat to end of string
- STCM R3,B'1100',CRCVAL Store final CRC
- CRCRTN LM R0,R15,CRCSAVE Restore registers
- BR R14 Return to caller
- SPACE
- CRCSAVE DS 8D Local save area
- EJECT
- *
- * Error message code
- *
- SPACE
- STATERR ST R15,RTNCODE Save return code from STATE
- LA R2,8(R1) R2 -> filename in PLIST
- C R15,=F'28' Return if STATE typed message
- BL CMSRTN
- BE STNOFIL RC = 28 is file not found
- * Else disk not accessed (RC = 36)
- LA R2,16(R2) R2 -> filemode in plist
- DMSERR NUM=69,LET=E,TEXT='Disk ''..'' not accessed', X
- SUB=(CHARA,((R2),1))
- B CMSRTN
- SPACE
- STNOFIL DMSERR NUM=2,LET=E, X
- TEXT='File ''....................'' not found', X
- SUB=(CHAR8A,(R2))
- B CMSRTN
- SPACE
- LRECLERR MVI RTNCODE+3,32 Set RC = 32
- DMSERR NUM=44,LET=E,TEXT='Record length exceeds allowable maxiX
- mum'
- B CMSRTN
- SPACE
- EXIERR LTR R15,R15 If non-zero RC, handle STATE error
- BNZ STATERR
- LA R2,8(R1) R2 -> filemame in plist
- DMSERR NUM=24,LET=E, X
- TEXT='File ''....................'' already exists', X
- SUB=(CHAR8A,(R2))
- MVI RTNCODE+3,28
- B CMSRTN
- SPACE
- ROERR EQU *
- USING ADTSECT,R2
- LA R2,ADTM Point to mode letter
- DROP R2
- DMSERR NUM=37,LET=E,TEXT='Disk ''..'' is read-only', X
- SUB=(CHARA,((R2),1))
- MVI RTNCODE+3,36
- B CMSRTN
- SPACE
- CMSRTN EQU * Return to CMS
- TM FLAGS,RDOPEN Is input file open?
- BZ RTN0 No, skip finis
- L R15,AFINIS
- LA R1,INPLIST
- BALR R14,R15 Close input file
- RTN0 TM FLAGS,WROPEN Is output file open?
- BZ RTN1 No, skip finis
- L R15,AFINIS
- LA R1,OUTPLIST
- BALR R14,R15 Close output file
- RTN1 DMSKEY RESET Restore user key
- SSM =X'FF' Allow interrupts
- L R15,RTNCODE R15 = return code
- LM R0,R14,REGSAVE Restore other registers
- BR R14 Return to caller
- EJECT
- *
- * GETID - Invoke IDENTIFY to get local node id. Set the
- * node id to blanks if any error.
- *
- SPACE
- GETID DS 0H
- STM R14,R1,GETSAVE Save registers
- MVC NODEID(8),=CL8' ' Initialize node id to blanks
- LA R1,IDPLIST Execute IDENTIFY
- SVC 202
- DC AL4(1)
- LTR R15,R15 Just return if any errors
- BNZ GETIDRTN
- RDTERM RDRESP Get response
- C R0,=F'19' At least 19 bytes?
- BL GETIDRTN No, just return
- MVC NODEID(8),RDRESP+12 Copy node id from IDENTIFY
- GETIDRTN LM R14,R1,GETSAVE Restore registers
- BR R14 Return
- SPACE
- GETSAVE DS 2D Save area: R14, R15, R0, R1
- IDPLIST DS 0D
- DC CL8'IDENTIFY' IDENTIFY command
- DC CL8'('
- DC CL8'LIFO'
- DC 8X'FF'
- RDRESP DS CL130 RDTERM buffer
- EJECT
- *
- * DECCVT -- Convert decimal number in plist to binary
- *
- * Entry: R1 -> 8-byte number, R14 = return address
- * Exit: R2 = -1 if conversion error, or contains binary number;
- * condition code set from R2
- *
- DECCVT DS 0H
- STM R3,R1,DECSAVE Save registers
- SR R2,R2 Result = 0
- LA R3,8 Examine 8 bytes
- SR R4,R4 R4 = 0 for IC
- * R1 -> first byte of token
- DECLOOP EQU * Scan number and accumulate result
- CLI 0(R1),C' ' Exit when blank encountered
- BE DECEND
- CLI 0(R1),C'0' Check for a valid digit
- BL DECERR
- CLI 0(R1),C'9'
- BH DECERR
- IC R4,0(R1) Get binary digit in R4
- SH R4,=H'240'
- MH R2,=H'10' Result = 10*result + digit
- AR R2,R4
- LA R1,1(R1) R1 -> next digit
- BCT R3,DECLOOP Repeat
- B DECEND Skip error result
- DECERR LH R2,=H'-1' Error: return -1
- DECEND LM R3,R1,DECSAVE Restore all registers except R2
- LTR R2,R2 Set condition code for caller
- BR R14 Return to caller
- SPACE
- DECSAVE DS 8D Save area R3...R15, R0, R1
- EJECT
- *
- * NUMTOSTR - Store character form of a number in a buffer.
- * At entry, R0 contains the number and R1 points to
- * the buffer. Returns the length of the string
- * stored in R0.
- *
- NUMTOSTR DS 0H
- STM R0,R15,NUMSAVE Save registers
- CVD R0,NUMBUF Convert number to decimal
- TM FLAGS2,EXECVAR+NOCOMMA Check if commas not wanted
- BNZ ALTEDIT
- MVC EDITBUFF(15),EDITPAT Copy pattern for EDMK
- LA R1,EDITBUFF+14 R1 -> last byte
- EDMK EDITBUFF(15),NUMBUF+2 Convert to characters
- LA R2,EDITBUFF+15 R2 -> past last byte
- B NUMEND
- SPACE
- ALTEDIT MVC EDITBUFF(12),EDITPAT2 Copy pattern for EDMK
- LA R1,EDITBUFF+11 R1 -> last byte
- EDMK EDITBUFF(12),NUMBUF+2 Convert to characters
- LA R2,EDITBUFF+12 R2 -> past last byte
- NUMEND SR R2,R1 Get length in R2
- ST R2,NUMSAVE Store to return in R0
- BCTR R2,0 Decrement for EX
- L R3,NUMSAVE+4 R3 -> buffer
- EX R2,NUMMVC Copy number to buffer
- LM R0,R15,NUMSAVE Return to caller
- BR R14
- SPACE
- NUMSAVE DS 8D Local save area
- NUMBUF DS 1D Buffer for CVD
- NUMMVC MVC 0(*-*,R3),0(R1) Copy number to buffer
- EDITPAT DC X'4020206B2020206B2020206B202120' EDIT pattern
- EDITPAT2 DC X'402020202020202020202120' alternate pattern
- EDITBUFF DS 15C Buffer for EDIT result
- EJECT
- *
- * SEC2DATE - Store the character form of a Macintosh date in a
- * buffer. At entry, R0 contains the number of seconds
- * since midnight, Jan. 1, 1904. R1 points to the buffer
- * which will contains the date. The length of the date
- * is returned in R0.
- *
- SEC2DATE DS 0H
- STM R0,R15,SECSAVE Save registers
- OI FLAGS2,NOCOMMA Suppress commas for NUMTOSTR
- * Get elapsed days, hours, minutes, seconds
- LR R1,R0 R0, R1 = total seconds
- SR R0,R0
- D R0,=F'86400' Divide to get days
- ST R1,SECDAYS Store elapsed days
- LR R1,R0 R0, R1 = remaining seconds
- SR R0,R0
- D R0,=F'3600' Divide to get hours
- ST R1,SECHRS Store elapsed hours
- LR R1,R0 R0, R1 = remaining seconds
- SR R0,R0
- D R0,=F'60' Divide to get mins, seconds
- ST R1,SECMIN Store elpased minutes
- ST R0,SECSEC Store elpased seconds
- * Calculate day of the week
- SR R0,R0 Divide days by 7
- L R1,SECDAYS
- D R0,=F'7'
- ST R0,SECWKDAY Store remainder
- * Calculate month, day and year from elapsed days
- L R3,SECDAYS R3 = elapsed days
- A R3,=F'1401' Add constant to get days from
- * March 1, 1900
- * Get 4*Jdate + 3
- SLL R3,2
- LA R3,3(R3)
- SR R2,R2 Divide by 1461
- D R2,=F'1461'
- * R2 = day, R3 = year
- SRL R2,2 Day = day/4 + 1
- LA R2,1(R2)
- MH R2,=H'5' Get (5*day-3)/153
- S R2,=F'3'
- SR R4,R4
- LR R5,R2
- D R4,=F'153'
- * R4 = day, R5 = month
- LR R2,R5 R2 = month
- SR R0,R0 Day = day/5 + 1
- LR R1,R4
- D R0,=F'5'
- LA R1,1(R1) R1 = day, R2 = month, R3 = year
- LA R2,3(R2) Month = Month + 3
- C R2,=F'12' If > 12, subtract 12
- BNH KEEPMON
- S R2,=F'12'
- LA R3,1(R3) And add 1 to year
- KEEPMON EQU *
- ST R1,SECDAY Store day of month
- ST R2,SECMONTH Store month
- LA R3,1900(R3) Add base year to year
- ST R3,SECYEAR
- * Format results in character string form
- SR R2,R2 R2 = string length
- L R3,SECSAVE+4 R3 -> next available byte
- L R1,SECWKDAY R1 = weekday (0 - 6)
- MH R1,=H'3' Convert to table offset
- LA R1,DAYLIST(R1) R1 -> weekday
- MVC 0(3,R3),0(R1) Copy weekday
- MVC 3(2,R3),=C', ' Append separator
- L R1,SECMONTH R1 = month (1 - 12)
- BCTR R1,0 Convert to table offset
- MH R1,=H'3'
- LA R1,MONLIST(R1) R1 -> month
- MVC 5(3,R3),0(R1) Copy month
- MVI 8(R3),C' ' Append separator
- LA R2,9(R2) Increment length
- LA R3,9(R3) Increment pointer
- L R0,SECDAY R0 = day of the month
- LR R1,R3 R1 -> buffer
- BAL R14,NUMTOSTR Store string in buffer
- AR R2,R0 Increment length
- AR R3,R0 Increment pointer
- MVC 0(2,R3),=C', ' Append separator
- LA R2,2(R2) Increment length
- LA R3,2(R3) Increment pointer
- L R0,SECYEAR R0 = year
- LR R1,R3 R1 -> buffer
- BAL R14,NUMTOSTR Store string in buffer
- AR R2,R0 Increment length
- AR R3,R0 Increment pointer
- MVC 0(2,R3),=C' ' Append separator
- LA R2,2(R2) Increment length
- LA R3,2(R3) Increment pointer
- L R0,SECHRS R0 = hours (0 - 23)
- C R0,=F'12' Morning if < 12
- BL SECAM
- * Else afternoon
- MVC AMPM(2),=C'PM' Store "PM"
- C R0,=F'12' If hours = 12, keep
- BE PMKEEP
- S R0,=F'12' Else subtract 12
- PMKEEP B USEHRS Ready to format hours
- SPACE
- SECAM MVC AMPM(2),=C'AM' Store "AM"
- LTR R0,R0 Use hours if > 0
- BNZ USEHRS
- LA R0,12 Else set hours to 12
- USEHRS LR R1,R3 R1 -> buffer
- BAL R14,NUMTOSTR Store string in buffer
- AR R2,R0 Increment length
- AR R3,R0 Increment pointer
- L R0,SECMIN R0 = minutes
- AH R0,=H'100' Add 100 to use 3 columns
- LR R1,R3 R1 -> buffer
- BAL R14,NUMTOSTR Store string in buffer
- MVI 0(R3),C':' Replace "1" by ":"
- AR R2,R0 Increment length
- AR R3,R0 Increment pointer
- L R0,SECSEC R0 = seconds
- AH R0,=H'100' Add 100 to use 3 columns
- LR R1,R3 R1 -> buffer
- BAL R14,NUMTOSTR Store string in buffer
- MVI 0(R3),C':' Replace "1" by ":"
- AR R2,R0 Increment length
- AR R3,R0 Increment pointer
- MVI 0(R3),C' ' Append separator
- MVC 1(2,R3),AMPM Append AM or PM
- LA R2,3(R2) R2 = final length
- ST R2,SECSAVE Store to return in R0
- NI FLAGS2,255-NOCOMMA Reset comma suppression
- LM R0,R15,SECSAVE Restore registers
- BR R14 Return to caller
- SPACE
- SECSAVE DS 8D Local save area
- SECDAYS DS 1F Elapsed days
- SECHRS DS 1F Elapsed hours
- SECMIN DS 1F Elapsed minutes
- SECSEC DS 1F Elapsed seconds
- SECWKDAY DS 1F Weekday (0 = Fri, 1 = Sat ...)
- SECDAY DS 1F Day of the month
- SECMONTH DS 1F Month
- SECYEAR DS 1F Year
- DAYLIST DC C'FriSatSunMonTueWedThu'
- MONLIST DC C'JanFebMarAprMayJunJulAugSepOctNovDec'
- AMPM DS 2C
- EJECT
- *
- * TYPEHDR - Type description of header information
- *
- TYPEHDR DS 0H
- STM R0,R15,TYPHDSAV Save registers
- L R8,=A(DATABUFF) R8 -> message buffer
- LINEDIT TEXT='File: ''....................''',RENT=NO, X
- SUB=(CHAR8A,IFN),DOT=NO,BUFFA=(R8),DISP=NONE
- SR R2,R2 R2 = message length
- IC R2,0(R8)
- LA R3,1(R2,R8) R3 -> next byte
- MVC 0(10,R3),=C' Format: ' Append format info.
- TM FLAGS,MACBIN Check for MacBinary
- BO FMTBIN
- MVC 10(6,R3),=C'BinHex' Else BinHex format
- LA R2,16(R2) Get new length
- B TYPEFMT Ready to type line
- SPACE
- FMTBIN MVC 10(9,R3),=C'MacBinary' MacBinary format
- LA R2,19(R2) Get new length
- TYPEFMT STC R2,0(R8) Store new length
- BAL R14,TYPEDESC Type or stack line
- MVC 1(11,R8),=C'Filename: ''' Generate filename msg.
- MVC 12(63,R8),HDFN append filename
- L R2,FRASCADR translate to EBCDIC
- TR 12(63,R8),0(R2)
- SR R1,R1 Get length of filename
- IC R1,HDFNLEN
- LA R1,12(R1) Add length of message
- STC R1,0(R8) Store length for TYPEDESC
- LA R1,0(R1,R8) R1 -> past filename
- MVI 0(R1),C'''' Append apostrophe
- BAL R14,TYPEDESC Type or stack line
- MVC 1(7,R8),=C'Type: ''' Generate type,
- MVC 8(4,R8),HDFTYP creator message
- TR 8(4,R8),0(R2) Translate to EBCDIC
- MVC 12(13,R8),=C''' Creator: '''
- MVC 25(4,R8),HDFCREAT
- TR 25(4,R8),0(R2) Translate to EBCDIC
- MVC 29(10,R8),=C''' Flags: '
- ICM R3,B'1100',HDFLAGS Get flags in msb of R3
- LA R4,FLAGTEXT R4 -> list of names
- LA R5,16 R5 = bit count
- LA R6,39 R6 = buffer offset
- FLGLOOP EQU * Loop to set flag names
- SR R2,R2 Get next bit in R2
- SLDL R2,1
- LTR R2,R2 Is bit set?
- BZ FLGNEXT No, skip name
- C R6,=F'39' First name?
- BE SKIPPLUS Yes, skip "+"
- IC R7,=C'+' Else append "+"
- STC R7,0(R6,R8)
- LA R6,1(R6)
- SKIPPLUS LA R7,0(R6,R8) R7 -> where to put text
- MVC 0(4,R7),0(R4) Copy flag name
- LA R6,4(R6)
- FLGNEXT LA R4,4(R4) R4 -> next name
- BCT R5,FLGLOOP
- C R6,=F'39' Any flags?
- BNE HAVEFLGS Yes, continue
- LA R7,0(R6,R8) Else append "none"
- MVC 0(4,R7),=C'none'
- LA R6,4(R6)
- HAVEFLGS BCTR R6,0 R6 = line length
- STC R6,0(R8) Store for TYPEDESC
- BAL R14,TYPEDESC Type or stack line
- ICM R3,B'1111',HDDATALN Get data fork length
- ICM R4,B'1111',HDRSCLN Get resource fork length
- MVC 1(16,R8),=C'Data fork size: ' Copy start of size
- LA R5,16 R5 = message length
- LA R6,1(R5,R8) R6 -> next byte
- LR R0,R3 R0 = data size
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store number in string form
- AR R5,R0 Update length and address
- AR R6,R0
- MVC 0(22,R6),=C'; Resource fork size: ' Copy rest
- LA R5,22(R5) Update length and address
- LA R6,22(R6)
- LR R0,R4 R0 = resource size
- LR R1,R6 R1 -> buffer
- BAL R14,NUMTOSTR Store number in string form
- AR R5,R0 Update length
- STC R5,0(R8) Store length for TYPEDESC
- BAL R14,TYPEDESC Type or stack line
- TM FLAGS,MACBIN MacBinary file?
- BZ TYPHEND No, all info. typed
- MVC 1(15,R8),=C' Created: ' Start of creation date
- LA R5,15 R5 = message length
- LA R1,1(R5,R8) R1 -> next byte
- ICM R0,B'1111',HDCRDATE R0 = creation date
- BAL R14,SEC2DATE Store date in character form
- AR R5,R0 Update length
- STC R5,0(R8) Store length for TYPEDESC
- BAL R14,TYPEDESC Type or stack line
- MVC 1(15,R8),=C'Last Modified: ' Start of last mod date
- LA R5,15 R5 = message length
- LA R1,1(R5,R8) R1 -> next byte
- ICM R0,B'1111',HDMDDATE R0 = creation date
- BAL R14,SEC2DATE Store date in character form
- AR R5,R0 Update length
- STC R5,0(R8) Store length for TYPEDESC
- BAL R14,TYPEDESC Type or stack line
- TYPHEND LA R1,=CL8'CONWAIT' Call CONWAIT to wait for
- SVC 202 output to finish
- DC AL4(1) (following code can take a while)
- LM R0,R15,TYPHDSAV Restore registers
- BR R14 Return to caller
- SPACE
- TYPHDSAV DS 8D Local save area
- EJECT
- *
- * TYPEDESC - Type a description line or stack the line (depending
- * on the options the user has specified). The first byte
- * of DATABUFF contains the line length, and is followed
- * by the text.
- *
- TYPEDESC DS 0H
- STM R0,R15,TYPSAVE Save registers
- L R2,=A(DATABUFF) R2 -> string length byte
- SR R1,R1 Get length in R1
- IC R1,0(R2)
- TM FLAGS,STKDESC Stacking requested?
- BO DOSTACK Yes, go do it
- STH R1,TYPLEN Store length for typing
- LA R1,TYPLIST R1 -> TYPLIN plist
- SVC 202 Type the line
- DC AL4(1) Ignore errors
- B TYPRTN Return
- SPACE
- DOSTACK MVI STKORDR,C'F' Set FIFO default order
- TM FLAGS,STKLIFO LIFO wanted?
- BZ KEEPFIFO No, keep FIFO
- MVI STKORDR,C'L' Else change FIFO to LIFO
- KEEPFIFO STC R1,STKLEN Store length for stacking
- LA R1,STKLIST R1 -> ATTN plist
- SVC 202 Stack the line
- DC AL4(1) Ignore errors
- TYPRTN LM R0,R15,TYPSAVE Restore registers
- BR R14 Return to caller
- SPACE
- TYPSAVE DS 8D Local save area
- EJECT
- *
- * VARHDR - Return header information in REXX variables. VARHDR
- * is called instead of TYPEHDR when the STEM option has
- * been specified.
- *
- VARHDR DS 0H
- STM R0,R15,VARSAVE Save registers
- L R8,=A(DATABUFF) R8 -> buffer for values
- L R1,=A(VARTAB) R1 -> FN string data
- MVI 0(R8),8 Store filename length
- MVC 1(8,R8),IFN Copy filename
- BAL R14,SETVAR Define stem.FN
- LA R1,4(R1) R1 -> FT string data
- MVI 0(R8),8 Store filetype length
- MVC 1(8,R8),IFT Copy filetype
- BAL R14,SETVAR Define stem.FT
- LA R1,4(R1) R1 -> FM string data
- MVI 0(R8),2 Store filemode length
- MVC 1(2,R8),IFM Copy filemode
- BAL R14,SETVAR Define stem.FM
- LA R1,4(R1) R1 -> FORMAT string data
- MVI 0(R8),6 Set to BinHex
- MVC 1(6,R8),=C'BinHex'
- TM FLAGS,MACBIN MacBinary?
- BZ USEFMT No, keep format
- MVI 0(R8),9 Set to MacBinary
- MVC 1(9,R8),=C'MacBinary'
- USEFMT BAL R14,SETVAR Define stem.FORMAT
- LA R1,4(R1) R1 -> NAME string data
- MVC 0(1,R8),HDFNLEN Copy length of name
- MVC 1(63,R8),HDFN Copy maximum text
- L R2,FRASCADR Translate to EBCDIC
- TR 1(63,R8),0(R2)
- BAL R14,SETVAR Define stem.NAME
- LA R1,4(R1) R1 -> TYPE string data
- MVI 0(R8),4 Length = 4
- MVC 1(4,R8),HDFTYP Copy type text
- TR 1(4,R8),0(R2) Translate to EBCDIC
- BAL R14,SETVAR Define stem.TYPE
- LA R1,4(R1) R1 -> CREATOR string data
- MVI 0(R8),4 Length = 4
- MVC 1(4,R8),HDFCREAT Copy type text
- TR 1(4,R8),0(R2) Translate to EBCDIC
- BAL R14,SETVAR Define stem.CREATOR
- LA R1,4(R1) R1 -> FLAGS string data
- ICM R3,B'1100',HDFLAGS Get flags in msb of R3
- LA R4,FLAGTEXT R4 -> list of names
- LA R5,16 R5 = bit count
- LA R6,1 R6 = buffer offset
- FLGLP2 EQU * Loop to set flag names
- SR R2,R2 Get next bit in R2
- SLDL R2,1
- LTR R2,R2 Is bit set?
- BZ FLGNXT2 No, skip name
- C R6,=F'1' First name?
- BE SKIPPL2 Yes, skip "+"
- IC R7,=C'+' Else append "+"
- STC R7,0(R6,R8)
- LA R6,1(R6)
- SKIPPL2 LA R7,0(R6,R8) R7 -> where to put text
- MVC 0(4,R7),0(R4) Copy flag name
- LA R6,4(R6)
- FLGNXT2 LA R4,4(R4) R4 -> next name
- BCT R5,FLGLP2
- C R6,=F'1' Any flags?
- BNE HAVEFLG2 Yes, continue
- LA R7,0(R6,R8) Else append "none"
- MVC 0(4,R7),=C'none'
- LA R6,4(R6)
- HAVEFLG2 BCTR R6,0 R6 = line length
- STC R6,0(R8) Store for SETVAR
- BAL R14,SETVAR Define stem.FLAGS
- LA R1,4(R1) R1 -> DATASIZE string data
- LR R2,R1 Save R1 across NUMTOSTR
- ICM R0,B'1111',HDDATALN R0 = size of data fork
- LA R1,1(R8) R1 -> buffer for number
- BAL R14,NUMTOSTR Convert to string
- STC R0,0(R8) Store string length
- LR R1,R2 Restore R1 for SETVAR
- BAL R14,SETVAR Define stem.DATASIZE
- LA R1,4(R1) R1 -> RESCSIZE string data
- LR R2,R1 Save R1 across NUMTOSTR
- ICM R0,B'1111',HDRSCLN R0 = size of resource fork
- LA R1,1(R8) R1 -> buffer for number
- BAL R14,NUMTOSTR Convert to string
- STC R0,0(R8) Store string length
- LR R1,R2 Restore R1 for SETVAR
- BAL R14,SETVAR Define stem.RESCSIZE
- TM FLAGS,MACBIN MacBinary file?
- BZ VARRTN No, all info. defined
- LA R1,4(R1) R1 -> CRDATE string data
- LR R2,R1 Save R1 across SEC2DATE
- ICM R0,B'1111',HDCRDATE R0 = creation date
- LA R1,1(R8) R1 -> buffer for number
- BAL R14,SEC2DATE Convert to string
- STC R0,0(R8) Store string length
- LR R1,R2 Restore R1 for SETVAR
- BAL R14,SETVAR Define stem.CRDATE
- LA R1,4(R1) R1 -> MDDATE string data
- LR R2,R1 Save R1 across SEC2DATE
- ICM R0,B'1111',HDMDDATE R0 = last modified date
- LA R1,1(R8) R1 -> buffer for number
- BAL R14,SEC2DATE Convert to string
- STC R0,0(R8) Store string length
- LR R1,R2 Restore R1 for SETVAR
- BAL R14,SETVAR Define stem.MDDATE
- VARRTN LM R0,R15,VARSAVE Restore registers
- BR R14 Return to caller
- SPACE
- VARSAVE DS 8D Local save area
- EJECT
- *
- * SETVAR - Define REXX variable to a given value. The variable
- * to be defined will be stemname.suffix, where "stemname"
- * was specified in the "STEM" option, and R1 contains the
- * address of a pointer to the length and text of "suffix".
- * The length and text of the variable's value is found in
- * DATABUFF.
- *
- SETVAR DS 0H
- STM R0,R15,SETSAVE Save registers
- MVC NAMEBUFF(8),STEMNAME Copy stem name
- L R3,STEMSIZE R3 = length of name
- LA R2,NAMEBUFF(R3) R2 -> next available byte
- MVI 0(R2),C'.' Append period
- LA R2,1(R2) Increment pointer
- LA R3,1(R3) Increment size
- L R1,0(R1) R1 -> length, text for suffix
- SR R5,R5 R5 = length
- IC R5,0(R1)
- LA R4,1(R1) R4 -> text
- BCTR R5,0 Decrement length for EX
- EX R5,NAMEMVC
- LA R3,1(R3,R5) R3 = length of variable name
- LA R2,NAMEBUFF R2 -> value of name
- L R1,=A(DATABUFF) R1 -> length, text of value
- SR R5,R5 R5 = length of value
- IC R5,0(R1)
- LA R4,1(R1) R4 -> value for variable
- LA R6,MYSHBLK Address shared variable block
- USING SHVBLOCK,R6
- XC SHVBLOCK(SHVBLEN),SHVBLOCK Initialize to zeros
- MVI SHVCODE,C'S' Store code to set a variable
- STM R2,R5,SHVNAMA Store name and value info.
- XC EXTPLIST(16),EXTPLIST Initialize extended plist
- DROP R6 Done with shared variable block
- LA R1,=CL8'EXECCOMM' R1 -> function name
- ST R1,EXTPLIST Store in extended plist
- ICM R1,B'1000',=X'02' Indicate subcommand call
- ST R6,EXTPLIST+12 Store A(shared variable block)
- LA R0,EXTPLIST R0 -> extended plist
- SVC 202 Invoke EXECCOMM to set variable
- DC AL4(1) Ignore errors
- LTR R15,R15 Check return code
- BZ SETRTN Ok if zero
- C R15,=F'-3' Check for environment error
- BE BADENV
- LR R2,R15 Save RC
- DMSERR NUM=632,LET=E, X
- TEXT='Error setting EXEC variable: RC=..... from ''EXECCX
- OMM'' function',SUB=(DEC,(R2))
- MVI RTNCODE+3,200 Set RC = 200
- B CMSRTN Return to CMS
- SPACE
- BADENV DMSERR NUM=631,LET=E, X
- TEXT='''STEM'' option is only available from an EXEC2 orX
- REXX exec'
- MVI RTNCODE+3,4 Set RC = 4
- B CMSRTN Return to CMS
- SPACE
- SETRTN LM R0,R15,SETSAVE Restore register
- BR R14 Return to caller
- SPACE
- SETSAVE DS 8D Local save area
- NAMEBUFF DS 3D Variable name constructed here
- MYSHBLK DS 4D Shared variable block
- EXTPLIST DS 4F Extended plist for EXECCOMM
- NAMEMVC MVC 0(*-*,R2),0(R4) Append suffix after stem
- EJECT
- *
- * BINHEX Data Area:
- *
- SPACE
- NODEID DS 1D Local node id
- BROWNID DC CL8'BROWNVM' Brown node id
- INPLIST DS 0D Input file all-purpose plist
- INCMMD DS CL8 command name (ignored for BALR)
- IFN DS CL8 filename
- IFT DS CL8 filetype
- IFM DS CL2 filemode
- RDUN1 DS H unused
- RDADDR DS A statefst addr.; rdbuf buffer
- RDBUFLTH DS F size of rdbuf buffer
- RDFV DS C recfm (F or V)
- RDFLAG DS X plist flag
- RDUN2 DS H unused
- RDLGTH DS A no. of bytes read (filled-in)
- RDITEM DS A extended item number
- RDITEC DS A extended number of items
- RDWP DS A write pointer
- RDRP DS A read pointer
- SPACE
- OUTPLIST DS 0D Output file all-purpose plist
- OUTCMMD DS CL8 command name (ignored for BALR)
- OFN DS CL8 filename
- OFT DS CL8 filetype
- OFM DS CL2 filemode
- WRUN1 DS H unused
- WRADDR DS A statefst addr.; wrbuf buffer
- WRBUFLTH DS F size of wrbuf buffer
- WRFV DS C recfm (F or V)
- WRFLAG DS X plist flag
- WRUN2 DS H unused
- WRUN3 DS A unused
- WRITEM DS A extended item number
- WRITEC DS A extended number of items
- WRWP DS A write pointer
- WRRP DS A read pointer
- SPACE
- DS 0D TYPLIN Plist to type description
- TYPLIST DC CL8'TYPLIN' command name for SVC 202
- DC AL1(1) obsolete terminal number
- DC AL3(DATABUFF+1) string address
- DC C'B' color (Black)
- DC AL1(0) flag byte
- TYPLEN DC AL2(*-*) string length
- SPACE
- DS 0D ATTN Plist to stack description
- STKLIST DC CL8'ATTN' command name for SVC 202
- STKORDR DC CL4'FIFO' LIFO or FIFO
- STKLEN DC AL1(*-*) string length
- DC AL3(DATABUFF+1) string length
- SPACE
- STEMNAME DS 1D Stem variable names
- HDREC DS 16D File header info. (128 bytes)
- ORG HDREC Define header fields
- HDVER DS 1X version byte
- HDFNLEN DS 1X length of filename
- HDFN DS 63C filename
- * start of Finder Info record
- HDFTYP DS 4C file type
- HDFCREAT DS 4C file creator
- HDFLAGS DS 1X finder flags
- HDFLAG2 DS 1X second flag byte
- HDVPOS DS 2X vertical position
- HDHPOS DS 2X horizontal position
- HDID DS 2X window or folder ID
- * end of Finder Info record
- HDPFLAG DS 1X "protected" flag
- HDZERO2 DS 1X zero
- HDDATALN DS 4X data fork length
- HDRSCLN DS 4X resource fork length
- HDCRDATE DS 4X creation date
- HDMDDATE DS 4X last modified date
- HDZERO3 DS 29X zero fill
- ORG
- BINLEN DS 1F Length of data in BINBUFF
- BINXTADR DS 1A Addr. for processing left over bits
- BINOFF DS 1F Offset into BINBUFF for GETSTR
- RDOFF DS 1F Offset into READBUFF for GTBINLIN
- EOFPOS DS 1F Position of EOFCHAR in current line
- CHRTOTAL DS 1F Total char. read by GETLINE
- CPS DS 1F Xfer rate chars./sec. or zero
- EXPLEN DS 1F No. of bytes in EXPBUFF
- WRLEN DS 1F HQX output line length
- STEMSIZE DS 1F Length of STEMNAME
- FRASCADR DS A A(ASCII to EBCDIC table)
- TOASCADR DS A A(EBCDIC to ASCII table)
- OPRTAB DS 0F Operand processing table
- DC CL8'?',AL4(QUESOPR)
- DC CL8'CHECK',AL4(CHKOPR)
- DC CL8'CONVERT',AL4(CVTOPR)
- DC CL8'DESCRIBE',AL4(DESCOPR)
- DC 8X'FF',AL4(-1)
- OPTTAB DS 0F Option processing table
- DC CL8'FIFO',AL4(STKOPT)
- DC CL8'LIFO',AL4(LIFOOPT)
- DC CL8'RATE',AL4(RATEOPT)
- DC CL8'STACK',AL4(STKOPT)
- DC CL8'STEM',AL4(STEMOPT)
- DC CL8'TO',AL4(TOOPT)
- DC 8X'FF',AL4(-1)
- CRCVAL DS 1H Calculated CRC
- CMPLBYTE DS 1X Last byte for compression
- CMPCNT DS 1X Compression count
- CMPCHAR DS 1C Character for compression
- BINLAST DS 1X Last character in BINBUFF
- BINEXTRA DS 1X Left over binary data
- OPRCODE DS 1C Code for first operand
- EOFCHAR DS 1C Invalid char. GETLINE stopped at
- CMPMODE DS 1X Current state for HQX compression
- HCMPCHAR DS 1C Last character for HQX compression
- CMPCOUNT DS 1X Character count for HQX comp.
- FLAGS DS 1X Flag byte
- MACBIN EQU X'01' Input file is MacBinary
- RDOPEN EQU X'02' Input file is open
- WROPEN EQU X'04' Output file is open
- HQXCOLON EQU X'08' Found first colon for HQX file
- HQXEOF EQU X'10' Found eof colon for HQX file
- X90DATA EQU X'20' Use data byte from last X'90'
- STKDESC EQU X'40' Stack description output
- STKLIFO EQU X'80' Stack output LIFO
- FLAGS2 DS 1X Second flag byte
- EXECVAR EQU X'01' Return header info in vars.
- NOCOMMA EQU X'02' Suppress commas for NUMTOSTR
- FLAGTEXT DC C'LockInvsBndlSystBozoBusyChngInit'
- DC C'CachShrdSwitNoSwRsv3Rsv2OwnADesk'
- LTORG
- DROP R11,R12,R13
- EJECT
- TOASCBRN DS 0D BROWN'S CP EBCDIC TO ASCII TRANSLATE TABLE
- DC X'000102037F097F7F7F7F7F0B0C0D0E0F' *....".""""".....*
- DC X'101112137F0A087F18197F7F1C1D1E1F' *....".."..""....*
- DC X'7F7F1C7F7F0A171B7F7F7F7F7F050607' *"".""..."""""...*
- DC X'7F7F167F7F1E7F047F7F7F1314157F1A' *"".""."."""...".*
- DC X'207F7F7F7F7F7F7F7F7F5B2E3C282B5E' *."""""""""$....;*
- DC X'267F7F7F7F7F7F7F7F7F21242A293B7E' *.""""""""".....=*
- DC X'2D2F7F7F7F7F7F7F7F7F7C2C255F3E3F' *..""""""""@..~..*
- DC X'7F7F7F7F7F7F7F7F607F3A2340273D22' *""""""""-".. ...*
- DC X'7F6162636465666768697F7B7F7F7F7F' *"/........"#""""*
- DC X'7F6A6B6C6D6E6F7071727F7D7F7F7F7F' *".,%_>?..."'""""*
- DC X'7F7F737475767778797A7F7F7F5B7F7F' *"".......:"""$""*
- DC X'7F7F7F7F7F7F7F7F7F7F7F7F7F5D7F7F' *""""""""""""")""*
- DC X'7F4142434445464748497F7F7F7F7F7F' *".........""""""*
- DC X'7F4A4B4C4D4E4F5051527F7F7F7F7F7F' *"..<(+|&..""""""*
- DC X'5C7F535455565758595A7F7F7F7F7F7F' **".......!""""""*
- DC X'303132333435363738397F7F7F7F7F7F' *..........""""""*
- SPACE
- FRASCBRN DS 0D BROWN'S CP ASCII TO EBCDIC TRANSLATE TABLE
- DC X'00010203372D2E2F1605250B0C0D0E0F'
- DC X'FF11123B3C3D322618193F271C1D1E1F'
- DC X'405A7F7B5B6C507D4D5D5C4E6B604B61'
- DC X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
- DC X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
- DC X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD4F6D'
- DC X'78818283848586878889919293949596'
- DC X'979899A2A3A4A5A6A7A8A98B6A9B5F07'
- DC X'00010203372D2E2F1605250B0C0D0E0F'
- DC X'FF11123B3C3D322618193F271C1D1E1F'
- DC X'405A7F7B5B6C507D4D5D5C4E6B604B61'
- DC X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
- DC X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
- DC X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD4F6D'
- DC X'78818283848586878889919293949596'
- DC X'979899A2A3A4A5A6A7A8A98B6A9B5F07'
- EJECT
- TOASCSTD DS 0D STANDARD CP EBCDIC TO ASCII TABLE
- DC X'000102037F097F7F7F7F7F0B0C0D0E0F' *....".""""".....*
- DC X'101112137F0A080018197F7F1C1D1E1F' *....".....""....*
- DC X'7F7F7F7F7F0A171B7F7F7F7F7F050607' *"""""..."""""...*
- DC X'7F7F167F7F7F7F047F7F7F7F14157F1A' *""."""".""""..".*
- DC X'207F7F7F7F7F7F7F7F7F7F2E3C282B7C' *.""""""""""....@*
- DC X'267F7F7F7F7F7F7F7F7F21242A293B5E' *.""""""""".....;*
- DC X'2D2F7F7F7F7F7F7F7F7F7C2C255F3E3F' *..""""""""@..~..*
- DC X'7F7F7F7F7F7F7F7F7F603A2340273D22' *"""""""""-.....*
- DC X'7F6162636465666768697F7F7F7F7F7F' *"/........""""""*
- DC X'7F6A6B6C6D6E6F7071727F7F7F7F7F7F' *".,%_>?...""""""*
- DC X'7F7E737475767778797A7F7F7F5B7F7F' *"=.......:"""$""*
- DC X'7F7F7F7F7F7F7F7F7F7F7F7F7F5D7F7F' *""""""""""""")""*
- DC X'7B4142434445464748497F7F7F7F7F7F' *#.........""""""*
- DC X'7D4A4B4C4D4E4F5051527F7F7F7F7F7F' *'.<(+|&..""""""*
- DC X'5C7F535455565758595A7F7F7F7F7F7F' **".......!""""""*
- DC X'303132333435363738397F7F7F7F7F7F' *..........""""""*
- SPACE
- FRASCSTD DS 0D STANDARD CP ASCII TO EBCDIC TABLE
- DC X'00010203372D2E2F1605250B0C0D0E0F'
- DC X'101112133C3D322618193F271C1D1E1F'
- DC X'405A7F7B5B6C507D4D5D5C4E6B604B61'
- DC X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
- DC X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
- DC X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'
- DC X'79818283848586878889919293949596'
- DC X'979899A2A3A4A5A6A7A8A9C04FD0A107'
- DC X'00010203372D2E2F1605250B0C0D0E0F'
- DC X'101112133C3D322618193F271C1D1E1F'
- DC X'405A7F7B5B6C507D4D5D5C4E6B604B61'
- DC X'F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F'
- DC X'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6'
- DC X'D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D'
- DC X'79818283848586878889919293949596'
- DC X'979899A2A3A4A5A6A7A8A9C04FD0A107'
- EJECT
- VALIDTAB DS 256X TRT table for valid characters
- * (Filled-in at initialization)
- CMPTAB DC 256X'00' TRT table for X'90'
- ORG CMPTAB+X'90'
- DC X'FF'
- ORG
- SPACE
- ASCTOBIN DS 0D
- DC 128X'FF'
- ORG ASCTOBIN+X'21'
- DC X'00010203040506070809' ! " # $ % & ' ( ) *
- DC X'0A0B0C' + , -
- ORG ASCTOBIN+X'30'
- DC X'0D0E0F10111213' 0 1 2 3 4 5 6
- ORG ASCTOBIN+X'38'
- DC X'1415' 8 9
- ORG ASCTOBIN+X'40'
- DC X'161718191A1B1C1D1E1F' @ A B C D E F G H I
- DC X'2021222324' J K L M N
- ORG ASCTOBIN+X'50'
- DC X'25262728292A2B' P Q R S T U V
- ORG ASCTOBIN+X'58'
- DC X'2C2D2E2F' X Y Z [
- ORG ASCTOBIN+X'60'
- DC X'30313233343536' i a b c d e f
- ORG ASCTOBIN+X'68'
- DC X'3738393A3B3C' h i j k l m
- ORG ASCTOBIN+X'70'
- DC X'3D3E3F' p q r
- ORG
- * ! " # $ % & ' ( ) * + , - 0 1 2 3 4 5 6 8 9 @
- BINTOASC DC X'2122232425262728292A2B2C2D30313233343536383940'
- * A B C D E F G H I J K L M N P Q R S T U V X Y
- DC X'4142434445464748494A4B4C4D4E505152535455565859'
- * Z [ i a b c d e f h i j k l m p q r
- DC X'5A5B6061626364656668696A6B6C6D707172'
- HQXMSG DC C'(This file must be converted with BinHex 4.0)'
- HQXMSGL EQU *-HQXMSG
- SPACE
- VARTAB DS 0A Address table for REXX var. names
- DC A(VAR1)
- DC A(VAR2)
- DC A(VAR3)
- DC A(VAR4)
- DC A(VAR5)
- DC A(VAR6)
- DC A(VAR7)
- DC A(VAR8)
- DC A(VAR9)
- DC A(VAR10)
- DC A(VAR11)
- DC A(VAR12)
- AVAR13 DC A(VAR13)
- AVAR14 DC A(VAR14)
- VAR1 DC AL1(VAR1L),C'FN' CMS filename
- VAR1L EQU *-VAR1-1
- VAR2 DC AL1(VAR2L),C'FT' CMS filetype
- VAR2L EQU *-VAR2-1
- VAR3 DC AL1(VAR3L),C'FM' CMS filemode
- VAR3L EQU *-VAR3-1
- VAR4 DC AL1(VAR4L),C'FORMAT' MacBinary or BinHex
- VAR4L EQU *-VAR4-1
- VAR5 DC AL1(VAR5L),C'NAME' Mac filename
- VAR5L EQU *-VAR5-1
- VAR6 DC AL1(VAR6L),C'TYPE' Mac type
- VAR6L EQU *-VAR6-1
- VAR7 DC AL1(VAR7L),C'CREATOR' Mac creator
- VAR7L EQU *-VAR7-1
- VAR8 DC AL1(VAR8L),C'FLAGS' Mac flags
- VAR8L EQU *-VAR8-1
- VAR9 DC AL1(VAR9L),C'DATASIZE' Mac data fork size
- VAR9L EQU *-VAR9-1
- VAR10 DC AL1(VAR10L),C'RESCSIZE' Mac resource fork size
- VAR10L EQU *-VAR10-1
- VAR11 DC AL1(VAR11L),C'CRDATE' Mac creation date
- VAR11L EQU *-VAR11-1
- VAR12 DC AL1(VAR12L),C'MDDATE' Mac last modified date
- VAR12L EQU *-VAR12-1
- VAR13 DC AL1(VAR13L),C'CHARCNT' Total character count
- VAR13L EQU *-VAR13-1
- VAR14 DC AL1(VAR14L),C'TIMEEST' Dowload time estimate
- VAR14L EQU *-VAR14-1
- SPACE
- EXPBUFF DS 6D 48-byte HQX expansion buffer
- WRITBUFF DS 8D 64-byte disk output buffer
- DATABUFF DS 16D 128-byte work buffer
- BINBUFF DS 25D Binary from READBUFF
- READBUFF DS 32D 256-byte disk input buffer
- ADT
- FSTB
- FVS
- NUCON
- SHVBLOCK
- END
- ---------- end of BINHEX ASSEMBLE -----------------------------------
- ---------- start of BINHEX HELPCMS: 224 lines follow ----------------
- ..fo off
- ..cs 1 on
-
- BINHEX
-
- Use the BINHEX command to work with Macintosh files containing binary data
- which are stored in CMS. BINHEX may be used with HQX files, such as those
- created by BinHex 4.0 on the Macintosh, and also with BIN files, such as those
- created by BinHex 5.0. BINHEX checks files in these formats, describes the
- contents of the files, and converts between the two formats.
- ..cs 1 off
- ..cs 2 on
- The format of the BINHEX command is:
-
- ?~~~~~~~~~~]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\
- k k k
- k BINHEX k ? | Check | Describe | COnvert fn <ft <fm >> [(options...[)]] k
- k k k
- k k Options: k
- k k ? \ ? \ ? \ k
- k k kTo fm k kStack k kFifo k k
- k k kRate cps k kLifo k kSTEm stm k k
- k k > ; > ; > ; k
- k k k
- >~~~~~~~~~~[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
- ..cs 2 off
- ..cs 3 on
-
- OPERANDS
-
- ? causes BINHEX to type a brief description of the command format,
- including all the valid operands and options. When "?" is specified,
- the remainder of the command line is ignored.
-
- Check cause BINHEX to check the input file for errors, such as missing or
- corrupted data. BINHEX will either report there are no errors, or
- respond with an error message describing the problem. BINHEX also
- checks the input file when the Describe or COnvert operand is
- specified.
-
- Describe causes BINHEX to display information about the input file, including
- the full Macintosh filename, the type, creator, flags values, and the
- sizes of the data and resource forks. See the "Responses" section
- below for examples of the information which is displayed.
-
- COnvert causes BINHEX to convert the input file from BinHex to MacBinary
- format or vice-versa. The resulting file has the same filename as
- the input file, and a filetype of either BIN (for MacBinary format)
- or HQX (for BinHex format). The file is written to the same disk as
- the input file, unless the "To" option has been specified.
-
- fn specifies the filename of the input file.
-
- ft specifies the filetype of the input file. When "ft" is omitted or
- specified as "*", all filetypes will be searched to find a match for
- "fn".
-
- fm specifies the filemode of the input file. When "fm" is omitted or
- specified as "*", all accessed disks will be searched for a file
- matching "fn" and "ft".
-
- OPTIONS
-
- To fm specifies the disk to which the output file will be written when the
- "COnvert" operand is specified. When "To" is omitted, the output
- file is written to the same disk as the input file.
-
- Rate cps specifies a file transfer rate in characters per second. When a rate
- is specified, the information displayed by the "Describe" function
- will include an estimate of the time required to download the file.
-
- Stack cause the output from the "Describe" function to be stacked in FIFO
- order. "Fifo" is a synonym for "Stack".
-
- Lifo causes the output from the "Describe" function to be stacked in LIFO
- order.
-
- Fifo cause the output from the "Describe" function to be stacked in FIFO
- order. "Stack" is a synonym for "Fifo".
-
- STEm stm causes the output from the "Describe" function to be stored directly
- into REXX or EXEC2 variables. "stm" is the name of the stem for
- these variables, i.e. the characters preceding a period in their
- names. Only the first eight characters of "stm" are significant.
- The following variables are defined:
-
- stm.FN CMS filename
- stm.FT CMS filetype
- stm.FM CMS filemode
- stm.FORMAT BinHex or MacBinary
- stm.NAME Mac filename
- stm.TYPE Mac type
- stm.CREATOR Mac creator
- stm.FLAGS Mac flags
- stm.DATASIZE Mac data fork size
- stm.RESCSIZE Mac resource fork size
- stm.CRDATE Mac creation date
- stm.MDDATE Mac last modified date
- stm.CHARCNT Total character count
- stm.TIMEEST Download time estimate
-
- The creation and last modified dates are not defined for BinHex
- format files, which do not include them. The time estimate is
- defined only when the Rate option has been specified.
-
- USING THE BINHEX COMMAND
-
- The BINHEX command allows Macintosh users to obtain information about files
- stored in CMS which would ordinarily not be available until the files had been
- downloaded to a Macintosh. The Check function verifies that a file will be
- accepted by BinHex on the Macintosh, and the Describe function provides
- detailed information about a file. With this information, a Macintosh user can
- often avoid spending time downloading unwanted files or files which contain
- errors. The COnvert function provides conversion between the two file formats
- BINHEX accepts: BinHex format and MacBinary format. Conversion is useful
- because each of these formats offers advantages for storing Macintosh programs.
-
- BinHex format is used by BinHex 4.0 on the Macintosh. It consists of a header,
- the data fork, and the resource fork of a Macintosh file, compressed and
- converted to printable characters. Converting a file from binary to printable
- characters increases its size (in spite of the inclusion of file compression).
- However, since they contain only printable characters, BinHex files can be
- included in electronic mail, and can be uploaded and downloaded in nearly any
- environment. In CMS, BinHex files usually are given filetypes containing
- "HQX", and may have fixed or variable-length records. The files usually begin
- with the line
-
- (This file must be converted with BinHex 4.0)
-
- MacBinary format is used by BinHex 5.0 and MacTerminal on the Macintosh. It is
- similar to BinHex format, but retains the file contents in binary form instead
- of converting to printable characters. It also includes the dates the
- Macintosh file was created and last modified, and some extra flag bits.
- MacBinary is the most compact format for storing a Macintosh file. However,
- because MacBinary files retain binary data, they can be uploaded and downloaded
- only by programs which use an 8-bit data path. Usually, such a path is not
- available for VM/CMS systems. Programs such as Kermit can simulate an 8-bit
- path using printable characters, but only at the expense of a much longer
- transfer time. MacBinary files in CMS usually are given filetypes containing
- "BIN". They consist of fixed-length 128-byte records.
-
- USAGE NOTES
-
- 1) Although the filetype of the input file will usually indicate which format
- it is in, BINHEX determines the file's format by examining its
- characteristics. If the file has fixed-length 128-byte records, BINHEX
- assumes MacBinary format. Otherwise, BINHEX assumes BinHex format.
-
- 2) The data in a BinHex format file begins with a line containing a colon in
- column one, and ends with a line having a colon as the last character.
- CMS BINHEX skips any other lines in the file. However, BinHex on the
- Macintosh only skips the comment line "(This file must be converted with
- BinHex 4.0)". Thus, even when the Check function reports no errors, it
- may still be necessary to delete extraneous lines from the BinHex file
- before BinHex on the Macintosh will accept the file.
-
- 3) BinHex format files do not contain all the information included in
- MacBinary files. In particular, the creation and last modified dates, and
- some flag bits are not stored. As a result, this information is lost when
- the COnvert function is used to convert from MacBinary to BinHex format.
-
- 4) BINHEX cannot detect if the input file is not in either MacBinary or
- BinHex format. In this case, BINHEX will usually assume the file is in
- BinHex format, and give an "unexpected end-of-file" message when it fails
- to find the first line of BinHex data.
-
- 5) For a BinHex file, the maximum line length BINHEX can process is 256.
-
- RESPONSES
-
- 'fn ft fm': No errors detected.
-
- This is the normal response from the Check function. This response
- is omitted when BINHEX is called from a CMS command, or from an exec
- file with "address COMMAND" in effect.
-
- File: 'STARS16 HQX T1' Format: BinHex
- Filename: 'Stars 1.6'
- Type: 'DFIL' Creator: 'DMOV' Flags: none
- Data fork size: 0; Resource fork size: 6,054
- Character count: 10,140.
-
- This is the response from the Describe function for a BinHex file
- when the Rate option is not used. This is the shortest possible
- description.
-
- File: 'TERM412 BIN M1' Format: MacBinary
- Filename: 'Term 4.12'
- Type: 'APPL' Creator: 'TRMA' Flags: Bndl+Init
- Data fork size: 0; Resource fork size: 52,947
- Created: Thu, May 28, 1987 2:01:25 AM
- Last Modified: Thu, May 28, 1987 2:02:04 AM
- Character count: 53,120 (4 minutes, 55 seconds at 180 cps).
-
- This is the response from the Describe function for a MacBinary file
- when the Rate option is used. This is the longest possible
- description.
-
- OTHER MESSAGES AND RETURN CODES
-
- DMSBIN631E 'STEM' option is only available from an EXEC2 or REXX exec.
- RC=4
- DMSBIN001E Error in command after 'token'. RC=24
- DMSBIN002I Issue BINHEX ? or HELP CMS BINHEX for more information.
- DMSBIN003E Invalid option 'xxxxxxxx'. RC=24
- DMSBIN010E Invalid rate 'xxxxxxxx'. RC=24
- DMSBIN048E Invalid mode 'xxxxxxxx'. RC=24
- DMSBIN637E Missing value for the 'STEM' option. RC=24
- DMSBIN002E File 'fn ft fm' not found. RC=28
- DMSBIN024E File 'fn ft fm' already exists. RC=28
- DMSBIN044E Record length exceeds allowable maximum. RC=32
- DMSBIN005E Invalid character 'x' in 'fn ft fm' at line mmmmmm position
- nnn. RC=36
- DMSBIN006E Unexpected end-of-file reading 'fn ft fm'. RC=36
- DMSBIN037E Disk 'mode' is read-only. RC=36
- DMSBIN069E Disk 'mode' not accessed. RC=36
- DMSBIN007E 'fn ft fm': CRC error for BinHex header. RC=44
- DMSBIN008E 'fn ft fm': CRC error for BinHex data fork. RC=44
- DMSBIN009E 'fn ft fm': CRC error for BinHex resource fork. RC=44
- DMSBIN104S Error 'nn' reading file 'fn ft fm' from disk. RC=1nn
- DMSBIN105S Error 'nn' writing file 'fn ft fm' on disk. RC=1nn
- DMSBIN632E Error setting EXEC variable: RC=nnnnn from 'EXECCOMM'. RC=200
-
- ..cs 3 off
- ---------- end of BINHEX HELPCMS ------------------------------------
- ---------- start of XMDMGEN C: 62 lines follow ----------------------
- /* This program generates the XMODEM CRC table in XMDMTAB ASSEMBLE. */
- /* Peter DiCamillo, June, 1987 */
-
- #include "stdio.h"
-
- main()
- ,
- FILE *io;
- unsigned int array[256];
- register char x1, x2, x3, x4, x5, x6, x7, x8;
- int count;
- int i, j, k;
- char ioline[132], iobuff[80];
-
- count = 0;
-
- for (x8=0; x8 < 2; x8++)
- for (x7=0; x7 < 2; x7++)
- for (x6=0; x6 < 2; x6++)
- for (x5=0; x5 < 2; x5++)
- for (x4=0; x4 < 2; x4++)
- for (x3=0; x3 < 2; x3++)
- for (x2=0; x2 < 2; x2++)
- for (x1=0; x1 < 2; x1++) ,
- array[count] = 0;
- if (x8 ~ x4) array[count] += 0x8000;
- if (x7 ~ x3) array[count] += 0x4000;
- if (x6 ~ x2) array[count] += 0x2000;
- if (x8 ~ x5 ~ x1) array[count] += 0x1000;
- if (x7) array[count] += 0x0800;
- if (x6) array[count] += 0x0400;
- if (x5) array[count] += 0x0200;
- if (x8 ~ x4) array[count] += 0x0100;
- if (x8 ~ x7 ~ x3) array[count] += 0x0080;
- if (x7 ~ x6 ~ x2) array[count] += 0x0040;
- if (x6 ~ x5 ~ x1) array[count] += 0x0020;
- if (x5) array[count] += 0x0010;
- if (x8 ~ x4) array[count] += 0x0008;
- if (x7 ~ x3) array[count] += 0x0004;
- if (x6 ~ x2) array[count] += 0x0002;
- if (x5 ~ x1) array[count] += 0x0001;
- count++;
- -
- /* Output assemble file with the table */
-
- io = fopen("xmdmtab assemble a (lrecl 80 recfm f","w");
- j = 6; /* number of contants on current line */
- strcpy(ioline,"XMDMTAB CSECT");
- for (i = 0; i < 256; i++) ,
- if (j == 6) ,
- fprintf(io, "%s\n", ioline);
- j = 0;
- strcpy(ioline," DC ");
- -
- if (j != 0) strcat(ioline,",");
- sprintf(iobuff,"X'%04x'",array[i]);
- strcat(ioline,iobuff);
- j++;
- -
- if (j != 0) fprintf(io, "%s\n", ioline);
- fclose(io);
- -
- ---------- end of XMDMGEN C -----------------------------------------
- ---------- start of XMDMTAB ASSEMBLE: 46 lines follow ---------------
- * Table for calculating XMODEM CRC; generated by XMDMGEN C
- XMDMTAB CSECT TABLE FOR GENERATING XMODEM CRC
- DC X'0000',X'1021',X'2042',X'3063',X'4084',X'50A5'
- DC X'60C6',X'70E7',X'8108',X'9129',X'A14A',X'B16B'
- DC X'C18C',X'D1AD',X'E1CE',X'F1EF',X'1231',X'0210'
- DC X'3273',X'2252',X'52B5',X'4294',X'72F7',X'62D6'
- DC X'9339',X'8318',X'B37B',X'A35A',X'D3BD',X'C39C'
- DC X'F3FF',X'E3DE',X'2462',X'3443',X'0420',X'1401'
- DC X'64E6',X'74C7',X'44A4',X'5485',X'A56A',X'B54B'
- DC X'8528',X'9509',X'E5EE',X'F5CF',X'C5AC',X'D58D'
- DC X'3653',X'2672',X'1611',X'0630',X'76D7',X'66F6'
- DC X'5695',X'46B4',X'B75B',X'A77A',X'9719',X'8738'
- DC X'F7DF',X'E7FE',X'D79D',X'C7BC',X'48C4',X'58E5'
- DC X'6886',X'78A7',X'0840',X'1861',X'2802',X'3823'
- DC X'C9CC',X'D9ED',X'E98E',X'F9AF',X'8948',X'9969'
- DC X'A90A',X'B92B',X'5AF5',X'4AD4',X'7AB7',X'6A96'
- DC X'1A71',X'0A50',X'3A33',X'2A12',X'DBFD',X'CBDC'
- DC X'FBBF',X'EB9E',X'9B79',X'8B58',X'BB3B',X'AB1A'
- DC X'6CA6',X'7C87',X'4CE4',X'5CC5',X'2C22',X'3C03'
- DC X'0C60',X'1C41',X'EDAE',X'FD8F',X'CDEC',X'DDCD'
- DC X'AD2A',X'BD0B',X'8D68',X'9D49',X'7E97',X'6EB6'
- DC X'5ED5',X'4EF4',X'3E13',X'2E32',X'1E51',X'0E70'
- DC X'FF9F',X'EFBE',X'DFDD',X'CFFC',X'BF1B',X'AF3A'
- DC X'9F59',X'8F78',X'9188',X'81A9',X'B1CA',X'A1EB'
- DC X'D10C',X'C12D',X'F14E',X'E16F',X'1080',X'00A1'
- DC X'30C2',X'20E3',X'5004',X'4025',X'7046',X'6067'
- DC X'83B9',X'9398',X'A3FB',X'B3DA',X'C33D',X'D31C'
- DC X'E37F',X'F35E',X'02B1',X'1290',X'22F3',X'32D2'
- DC X'4235',X'5214',X'6277',X'7256',X'B5EA',X'A5CB'
- DC X'95A8',X'8589',X'F56E',X'E54F',X'D52C',X'C50D'
- DC X'34E2',X'24C3',X'14A0',X'0481',X'7466',X'6447'
- DC X'5424',X'4405',X'A7DB',X'B7FA',X'8799',X'97B8'
- DC X'E75F',X'F77E',X'C71D',X'D73C',X'26D3',X'36F2'
- DC X'0691',X'16B0',X'6657',X'7676',X'4615',X'5634'
- DC X'D94C',X'C96D',X'F90E',X'E92F',X'99C8',X'89E9'
- DC X'B98A',X'A9AB',X'5844',X'4865',X'7806',X'6827'
- DC X'18C0',X'08E1',X'3882',X'28A3',X'CB7D' 'DB5C'
- DC X'EB3F',X'FB1E',X'8BF9',X'9BD8',X'ABBB',X'BB9A'
- DC X'4A75',X'5A54',X'6A37',X'7A16',X'0AF1',X'1AD0'
- DC X'2AB3',X'3A92',X'FD2E',X'ED0F',X'DD6C',X'CD4D'
- DC X'BDAA',X'AD8B',X'9DE8',X'8DC9',X'7C26',X'6C07'
- DC X'5C64',X'4C45',X'3CA2',X'2C83',X'1CE0',X'0CC1'
- DC X'EF1F',X'FF3E',X'CF5D',X'DF7C',X'AF9B',X'BFBA'
- DC X'8FD9',X'9FF8',X'6E17',X'7E36',X'4E55',X'5E74'
- DC X'2E93',X'3EB2',X'0ED1',X'1EF0'
- END
- ---------- end of XMDMTAB ASSEMBLE ----------------------------------
-